Exploring dual-cue approach
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(ggplot2)
library(here)
here() starts at /Users/avrilwang/Desktop/Project-Plasmodium
library(deSolve)
library(crone)
library(optimParallel)
Loading required package: parallel
library(doParallel)
Loading required package: foreach
Loading required package: iterators
library(doRNG)
Loading required package: rngtools
library(arrow)
Attaching package: ‘arrow’
The following object is masked from ‘package:utils’:
timestamp
library(stringr)
library(parallel)
library(ggpubr)
library(microbenchmark)
library(profvis)
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
library(RANN)
parameters_tsukushi <- c(R1 = 8.89*(10^6), # slightly higher
lambda = 3.7*(10^5),
mu = 0.025,
p = 8*(10^-6), # doubled form original
alpha = 1,
alphag = 2,
beta = 5.721,
mum = 48,
mug = 4,
I0 = 43.85965,
Ig0 = 0,
a = 150,
b = 100,
sp = 1,
psin = 16.69234,
psiw = 0.8431785,
phin = 0.03520591,
phiw = 550.842,
iota = 2.18*(10^6),
rho = 0.2627156)
I_range_none <- seq(0, 6*(10^6), by = (6*(10^6))/500)
I_range_log <- seq(0, log10(6*(10^6)), by = (log10(6*(10^6)))/500)
G_range_none <- seq(0, 6*(10^4), by = (6*(10^4))/500)
G_range_log <- seq(0, log10(6*(10^4)), by = (log10(6*(10^4)))/500)
testing out mgcv dual cue spline surface. looks good.
note that if we go with ti, than we have only interactions between the 2 cues whereas te includes both main effect and interaction. ti gives us 5 parameters to optimze whereas te gives us 9. We should compare the two
source(here("functions/chabaudi_si_clean.R"))
# smaller division
cue_range <- seq(0, 6*(10^6), by = (6*(10^6))/500)
cue_range_b <- seq(0, 6*(10^4), by = (6*(10^4))/500)
parameters_cr <- rep(-0.5,9)
cr_grid <- expand.grid(cue_range, cue_range_b)
## rename
names(cr_grid) <- c("cue_range", "cue_range_b")
## create dummy y
dummy_y <- runif(length(cue_range_b), 0, 1)
## put together df
dummy_df <- data.frame(cue_range, cue_range_b, dummy_y)
## gam model
dummy_cr.mod <- mgcv::gam(dummy_y ~ te(cue_range, cue_range_b,
bs = c("tp", "tp")
k = c(3,3)),
data = dummy_df,
method = "REML")
## assign parameters
dummy_cr.mod$coefficients <- parameters_cr
# exponential transformation to limit conversion rate to between 0 and 1
cr_fun <- function(cue_1, cue_2){
res <- exp(-exp(mgcv::predict.gam(dummy_cr.mod,
newdata = data.frame("cue_range" = cue_1,
"cue_range_b" = cue_2))))
return(res)
}
cutting down computational time
source(here("functions/chabaudi_si_clean.R"))
source(here("functions/test.R"))
# each run takes around 1 minute (cr_fun) (100 divisions)
# switching to nn2 takes 145 seconds
# increasing divisons to 500 using predict.gam takes still around 57 seconds. So increasing to 500 doesn't seem like a bad idea
system.time(test(parameters_cr = rep(0.5, 5),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.001),
cue = "I",
cue_b = "G",
cue_range = I_range_log,
cue_range_b = G_range_log,
solver = "vode",
log_cue = "log10",
log_cue_b = "log10"
))
making shit go fast! Need to cut down on time to get cr from function
cue_range <- I_range_log
cue_range_b <- G_range_log
cr_grid <- expand.grid(cue_range, cue_range_b)
## rename
names(cr_grid) <- c("cue_range", "cue_range_b")
## create dummy y
dummy_y <- runif(length(cue_range_b), 0, 1)
## put together df
dummy_df <- data.frame(cue_range, cue_range_b, dummy_y)
## gam model
dummy_cr.mod <- mgcv::bam(dummy_y ~ ti(cue_range, cue_range_b,
k = c(3,3)),
data = dummy_df)
## assign parameters
dummy_cr.mod$coefficients <- rep(0.5,5)
# original function of getting cr
cr_fun <- function(cue_1, cue_2){
exp(-exp(mgcv::predict.bam(dummy_cr.mod,
newdata = data.frame("cue_range" = cue_1,
"cue_range_b" = cue_2),
n.threads = 3)))
}
cr_res <- exp(-exp(mgcv::predict.gam(dummy_cr.mod,
newdata = cr_grid)))
cr_df <- cbind(cr_grid, cr_res)
cue_1 <- 1
cue_2 <- 0.5
# another function for nearnest neighoubrs
nn_fun <- function(cue_1, cue_2){
cr_df[nn2(data=cr_grid, query = cbind(cue_1, cue_2), k=1, treetype= "kd",
searchtype = "priority")[[1]],3]
}
nn_fun2 <- function(cue_1, cue_2){
cr_df[FNN::knnx.index(data=cr_grid, query = cbind(cue_1, cue_2), k = 1, algorithm = "kd_tree"),3]
}
# very similar
cr_fun(1,1)
nn_fun(1,1)
nn_fun2(1,1)
# gam.predict is faster
microbenchmark(cr_fun(1,1))
microbenchmark(nn_fun(1,1))
microbenchmark(nn_fun2(1,1))
sanity checkz
source(here("functions/test.R"))
# switching between cue and cue_b. should not make a difference
# 4.469067
test(parameters_cr = rep(0.5, 5),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.01),
cue = "I",
cue_b = "G",
cue_range = I_range_log,
cue_range_b = G_range_log,
solver = "vode",
log_cue = "log10",
log_cue_b = "log10"
)
# 4.469066. good
test(parameters_cr = rep(0.5, 5),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.01),
cue = "G",
cue_b = "I",
cue_range = G_range_log,
cue_range_b = I_range_log,
solver = "vode",
log_cue = "log10",
log_cue_b = "log10"
)
# short time steps vs longer time steps. barely made a difference
# 4.46904
test(parameters_cr = rep(0.5, 5),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.001),
cue = "I",
cue_b = "G",
cue_range = I_range_log,
cue_range_b = G_range_log,
solver = "vode",
log_cue = "log10",
log_cue_b = "log10"
)
# changing logs on cue_b
# 6.20639
test(parameters_cr = rep(0.5, 5),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.01),
cue = "I",
cue_b = "G",
cue_range = I_range_log,
cue_range_b = G_range_none,
solver = "vode",
log_cue = "log10",
log_cue_b = "none"
)
# changing logs on cue
# 5.110873
test(parameters_cr = rep(0.5, 5),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.01),
cue = "I",
cue_b = "G",
cue_range = I_range_none,
cue_range_b = G_range_log,
solver = "vode",
log_cue = "none",
log_cue_b = "log10"
)
# checing single cue infection. same
## 4.724804
test(parameters_cr = rep(0.5, 4),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.01),
cue = "I",
cue_range = I_range_none,
solver = "vode",
log_cue = "none",
)
# 4.724804
chabaudi_si_clean(parameters_cr = rep(0.5, 4),
immunity = "tsukushi",
parameters = parameters_tsukushi,
time_range = seq(0, 20, 0.01),
cue = "I",
cue_range = I_range_none,
solver = "vode",
log_cue = "none",
)
#————————————————–# # remaking of co-infection reaction norm #————————————————–#
source(here("functions/chabaudi_ci_clean.R"))
source(here("functions/par_to_df.R"))
function for getting conversion rate reaction norm and dynamics
get_ci_dyn <- function(df){
# get heavisde transformation
heaviside_trans <- function(cue_range, max){
crone::heaviside(cue_range)*(cue_range)+(crone::heaviside(cue_range-max)*(max-cue_range))
}
# read in df info
cue_1 <- ifelse(stringr::str_detect(df$cue, "-i"),
gsub("*-i", "1", df$cue),
df$cue)
cue_2 <- ifelse(stringr::str_detect(df$cue, "-i"),
gsub("*-i", "2", df$cue),
df$cue)
log <- ifelse(stringr::str_detect(df$log, "log"),
"log10", "none")
# get parameter
par <- c(df$var1, df$var2, df$var3, df$var4)
cue_range <- seq(df$low, df$high, by = df$by)
label <- df$label
# get dynamics
dyn <- chabaudi_ci_clean(parameters_cr_1 = par,
parameters_cr_2 = par,
immunity = "tsukushi",
parameters = parameters_tsukushi,
cue_1 = cue_1,
cue_2 = cue_2,
cue_range_1 = cue_range,
cue_range_2 = cue_range,
log_cue_1 = log,
log_cue_2 = log,
solver = "vode",
time_range = seq(0, 30, 0.001),
dyn = T)
dyn2 <- data.frame(dyn, label = rep(label, nrow(dyn)))
# get reaction norm
rn <- par_to_df(par = par, cue_range = cue_range)
# get rug
## if + in cue, need to filter out those variables and add together
if(stringr::str_detect(cue_1, "\\+")){
cue_split <- stringr::str_split(string = cue_1, pattern = "\\+", simplify = T)
## get the two cues
cue_temp_1 <- cue_split[[1]]
cue_temp_2 <- cue_split[[2]]
## filter dyn
rug <- dyn2 %>%
filter(variable == cue_temp_1 | variable == cue_temp_2) %>%
dplyr::group_by(time) %>%
dplyr::mutate(sum = sum(value)) %>%
select(time, value = sum, label)
}
## if sum
if(cue_1 == "sum"){
## filter dyn
rug <- dyn2 %>%
filter(variable == "I1" | variable == "I2" | variable == "Ig1" | variable == "Ig2") %>%
dplyr::group_by(time) %>%
dplyr::mutate(sum = sum(value)) %>%
select(time, value = sum, label)
}
# for simplified cue
if(stringr::str_detect(cue_1, "\\+", negate = T) && cue_1 != "sum"){
rug <- dyn2 %>%
dplyr::filter(variable == cue_1) %>%
dplyr::select(time, value, label)}
# for logged, backtransform cue range of reaction norm
rn2 <- rn
if(stringr::str_detect(log, "log")){rn2$cue_range <- 10^(rn2$cue_range)}
# append label to reaction norm, dyn, and rug
rn2 <- data.frame(rn2, label = rep(label, nrow(rn)))
return(list(dyn2, rn2, rug))
}
read in co_infection opt
ci_opt.df <- read.csv(here("data/ci_opt.csv"))
cue_range_ci <- read.csv(here("data/cue_range_ci.csv"))
# join with cue range
ci_opt.df <- ci_opt.df %>% left_join(select(cue_range_ci, id, low, high, by), by = c("id" = "id"))
# split
ci_opt.ls <- split(ci_opt.df, seq(nrow(ci_opt.df)))
# loop
ci_opt.dyn <- lapply(ci_opt.ls, get_ci_dyn)
# bind together dynamics
dyn.ls <- lapply(ci_opt.dyn, function(x)x[[1]])
ci_dyn.df <- do.call(rbind, dyn.ls)
write_parquet(ci_dyn.df, here("data/ci_dyn/ci_dyn.parquet"))
rn.ls <- lapply(ci_opt.dyn, function(x)x[[2]])
ci_rn.df <- do.call(rbind, rn.ls)
write_parquet(ci_rn.df, here("data/ci_dyn/ci_rn.parquet"))
rug.ls <- lapply(ci_opt.dyn, function(x)x[[3]])
ci_rug.df <- do.call(rbind, rug.ls)
write_parquet(ci_rug.df , here("data/ci_dyn/ci_rug.parquet"))
get in single infection reaction norm to match
si_opt.df <- read.csv(here("data/si_opt.csv"))
cue_range_si <- read.csv(here("data/cue_range_si.csv"))
si_opt.df <- si_opt.df %>% left_join(select(cue_range_si, id, low, high, by, label), by = "id")
# function to get single infection reaction norm
get_si_rn <- function(df){
par <- c(df$var1, df$var2, df$var3, df$var4)
cue_range <- seq(df$low, df$high, by = df$by)
rn <- par_to_df(par = par, cue_range = cue_range)
# for logged, backtransform cue range of reaction norm
rn2 <- rn
if(stringr::str_detect(df$log, "log")){rn2$cue_range <- 10^(rn2$cue_range)}
# append label to reaction norm, dyn, and rug
rn2 <- data.frame(rn2, id = df$id, label = rep(df$label, nrow(rn)))
return(rn2)
}
# rn function and bind together
si_opt.ls <- split(si_opt.df, seq(nrow(si_opt.df)))
si_opt.rn <- lapply(si_opt.ls, get_si_rn)
si_opt.rn2 <- do.call(rbind, si_opt.rn)
get single infeciton rug
si_dyn <- read_parquet(here("data/si_dyn/si_dyn_30.parquet"))
# join to get label
si_dyn.df <- left_join(si_dyn, si_opt.df, by = "id")
# process get rug
get_rug <- function(df){
cue <- unique(df$cue)
if(stringr::str_detect(cue, "\\+")){
cue_split <- stringr::str_split(string = cue, pattern = "\\+", simplify = T)
## get the two cues
cue_temp_1 <- cue_split[[1]]
cue_temp_2 <- cue_split[[2]]
## filter dyn
rug <- df %>%
filter(variable == cue_temp_1 | variable == cue_temp_2) %>%
dplyr::group_by(time) %>%
dplyr::mutate(sum = sum(value)) %>%
select(time, value = sum, label)
}
# for simplified cue
if(stringr::str_detect(cue, "\\+", negate = T)){
rug <- df %>%
dplyr::filter(variable == cue) %>%
dplyr::select(time, value, label)}
return(rug)
}
# split based on individual labels
si_dyn.ls <- si_dyn.df %>% group_split(id)
# run function to get rug
si_rug <- mclapply(si_dyn.ls, get_rug)
si_rug.df <- do.call(rbind, si_rug)
process reaction norm data to limit reaction norm to around the infection space

match single infection rn with coinfection
plot reaction norm
c
function (...) .Primitive("c")
#—————————————–# # plot maximum fitness accumulation for both si and ci #—————————————–#
ez_label <- read.csv(here("data/ez_label.csv"))
process single infection data
# import in si maximum transmission potential
si_dyn.df <- read_parquet(here("data/si_dyn/si_dyn_30.parquet"))
# get maximum tau_cum for 30 days
si_max_tau <- si_dyn.df %>%
filter(variable == "tau_cum") %>%
group_by(id) %>%
summarise(fitness_si = max(value))
process co-infection data
# import in co-infeciton data, 30 days simulation
ci_dyn.df <- read_parquet(here("data/ci_dyn/ci_dyn.parquet"))
# get maximum tau_cum. Note multiplied by 2 to get total fitness for both strains, given that both are sadiptng the same strategy, we consider them the same genotye
ci_max_tau <- ci_dyn.df %>%
filter(variable == "tau_cum1") %>%
group_by(label) %>%
summarise(fitness_ci = max(value, na.rm = T))
get label and join together 2 dataframes
si_ci_max_tau <- ci_max_tau %>%
left_join(ez_label, by = c("label" = "label_ci")) %>%
left_join(si_max_tau, by = c("id_si" = "id"))
plot
ggsave(here("figures/report21/si_ci_fitness.png"), height = 5)
Saving 7 x 5 in image
#—————————————# # time series conversion rate (line form) #—————————————#
single infection
cr_si <- si_dyn.df %>%
filter(variable == "cr")
# good cue bad cue
si_cue_dv <- si_max_tau %>%
mutate(classification = case_when(
fitness_si > 10.5 ~ "High-performing",
fitness_si <= 10.5 ~ "Poor-performing"
))
# join with classificaiton
cr_si.df <- cr_si %>% left_join(si_cue_dv) %>% left_join(ez_label, by = c("id" = "id_si"))
Joining, by = "id"
# split into top erforming and poor-performing cues
cr_si.high <- cr_si.df %>% filter(classification == "High-performing")
cr_si.poor <- cr_si.df %>% filter(classification == "Poor-performing")
# plot
cr_si_pl.pre <- ggplot() +
geom_line(data = cr_si.poor, aes(x= time, y = value, group = id), color = "dark grey") +
labs(color = "Single infection\nhigh-performing cues", x = "Time (days)", y = "Conversion rate") +
theme_bw()+ scale_y_continuous(labels = function(x) format(x, scientific = TRUE, accuracy = 0.1)) +
guides(shape = FALSE)
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
cr_si_pl <- cr_si_pl.pre +
geom_line(data = cr_si.high, aes(x= time, y = value, group = ez_label_si, color = ez_label_si), size = 1) +
scale_color_manual(values=c( "#4575b4", "#fc8d59", "#fdcb44", "#91bfdb"))
co-infection
# get relevent variables
cr_ci <- ci_dyn.df %>%
filter(variable == "cr_1")
# good cue bad cue
ci_cue_dv <- ci_max_tau %>%
mutate(classification = case_when(
fitness_ci > 2.25 ~ "High-performing",
fitness_ci <= 2.25 ~ "Poor-performing"
))
si_cue_dv
# join with classificaiton
cr_ci.df <- cr_ci %>% left_join(ci_cue_dv )%>% left_join(ez_label, by = c("label" = "label_ci"))
# split into top erforming and poor-performing cues
cr_ci.high <- cr_ci.df %>% filter(classification == "High-performing")
cr_ci.poor <- cr_ci.df %>% filter(classification == "Poor-performing")
# plot
cr_ci_pl.pre <- ggplot() +
geom_line(data = cr_ci.poor, aes(x= time, y = value, group = label), color = "dark grey", alpha = 0.5) +
labs(color = "Co-infection\nhigh-performing cues", x = "Time (day)", y = "Conversion rate") +
theme_bw()+ scale_y_continuous(labels = function(x) format(x, scientific = TRUE, accuracy = 0.1)) +
guides(shape = FALSE)
cr_ci_pl <- cr_ci_pl.pre +
geom_line(data = cr_ci.high, aes(x= time, y = value, group = ez_label, color = ez_label), size = 1) +
scale_color_manual(values=c( "#4575b4", "#fc8d59", "#fdcb44", "#91bfdb"))
arrange together
cr_pl <- ggarrange(cr_si_pl, cr_ci_pl, align = "hv", ncol = 1)
#—————————————# # Time series conversion rate (heatmap) #—————————————# note that the order of cues is sorted by descending 30-days fitness. # single infection
cr_hm_si.pl1 <- ggplot() +
geom_tile(data = cr_si.poor, aes(x = time, y = forcats::fct_reorder(ez_label_si, fitness_si), fill = value)) +
labs(x = "Time (days)", y = "Low performing\nsingle infection cues", fill = "Conversion rate") +
scale_fill_viridis_c(limits = c(0, 1)) +
xlim(1, 30) +
theme_bw()
cr_hm_si.pl2 <- ggplot() +
geom_tile(data = cr_si.high, aes(x = time, y = forcats::fct_reorder(ez_label_si, fitness_si), fill = value)) +
labs(x = "", y = "High performing\nsingle infection cues", fill = "Conversion rate") +
scale_fill_viridis_c(limits = c(0, 1)) +
xlim(1, 30) +
theme_bw()
co-infection
cr_hm_ci.pl1 <- ggplot() +
geom_tile(data = cr_ci.poor, aes(x = time, y = forcats::fct_reorder(ez_label, fitness_ci), fill = value)) +
labs(x = "Time (days)", y = "Low performing\nco-infection infection cues", fill = "Conversion rate") +
scale_fill_viridis_c(limits = c(0, 1)) +
xlim(1, 30) +
theme_bw() +
theme(legend.position = "none")
cr_hm_ci.pl2 <- ggplot() +
geom_tile(data = cr_ci.high, aes(x = time, forcats::fct_reorder(ez_label, fitness_ci), fill = value)) +
labs(x = "", y = "High performing\nco-infection cues", fill = "Conversion rate") +
scale_fill_viridis_c(limits = c(0, 1)) +
xlim(1, 30) +
theme_bw() +
theme(legend.position = "none")
cr_hm.pl <- ggarrange(cr_hm_si.pl2, cr_hm_ci.pl2, cr_hm_si.pl1, cr_hm_ci.pl1, align = "hv", ncol = 2, nrow = 2, common.legend = T)
Warning: Removed 6000 rows containing missing values (geom_tile).
Warning: Removed 6000 rows containing missing values (geom_tile).
Warning: Removed 4000 rows containing missing values (geom_tile).
Warning: Removed 10000 rows containing missing values (geom_tile).
Warning: Removed 12000 rows containing missing values (geom_tile).
ggsave(here("figures/report21/conversion_rate_heatmap.png"), height = 5.5, width = 12)

#—————————————# # disase curve #—————————————# note we are using the same 30 days infection dynamics from before
for single infection
note that we are dividing the cues into good and bad based on arbitrary cut off at 10.5

co-infection

# plot both single and co-infeciton disease curve together
disease_curve_pl <- ggarrange(disease_curve_pl.1, disease_curve_pl.2, align = "hv", heights = c(0.75, 1))
Error in ggarrange(disease_curve_pl.1, disease_curve_pl.2, align = "hv", :
object 'disease_curve_pl.1' not found
#———————–# Arranging opt_cue figure #———————–#
ggarrange(opt_cue_pl.A, opt_cue_pl.BC, labels = c("A", ""), ncol = 2, widths = c(0.75, 1))
Warning: ggrepel: 7 unlabeled data points (too many overlaps). Consider increasing max.overlaps

ggarrange(opt_cue_pl.A, opt_cue_pl.BC, labels = c("A", ""), ncol = 2, widths = c(0.75, 1))
Warning: ggrepel: 7 unlabeled data points (too many overlaps). Consider increasing max.overlaps
ggsave(here("figures/report21/opt_cue_final.png"), width = 14, height = 9)

#———————————# # remaking heatmaps #———————————# #———————————-# # static heatmap #———————————-# # processing data
max(static.df4$fitness_diff)
[1] 0.9096023
get heatmap
ggsave(here("figures/report21/static_heatmap.png"), width = 10)
Saving 10 x 7 in image
#————————-# # ci invasion matrix #————————-#
# import and process ci-invasion data
invade.ls <- list.files(here("data/ci_invasion/"), pattern = "*.csv", full.names = T)
invade.ls2 <- lapply(invade.ls, read.csv)
invade.df <- do.call(rbind, invade.ls2)
#write.csv(invade.df, row.names = F, here("data/ci_invasion.csv"))
invade.df <- read.csv(here("data/ci_invasion.csv"))
sanity check. all invasion combination hsould have a fitness higher than static competition
sc_static.df <- static.df %>%
mutate(fitness_static = fitness_1 - fitness_2) %>%
select(id_1, id_2, fitness_static)
# get reverse
sc_static.df2 <- sc_static.df
sc_static.df2$fitness_static <- sc_static.df$fitness_static*-1
names(sc_static.df2) <- c("id_2", "id_1", "fitness_static")
# combine
sc_static.df3 <- rbind(sc_static.df, sc_static.df2)
# left join. none of these are huge and invasion runs for 20 days whereas static competition runs for 30 days. looks good
invade.df %>%
left_join(sc_static.df3, by = c("mut_id"= "id_1", "res_id" = "id_2")) %>%
mutate(invade_static = fitness - fitness_static) %>%
filter(invade_static < 0)
process data for invasion matrix
create summary bar chart

plot togehter
invasion.pl <- ggarrange(invasion.pl1, invasion.pl2, align = "h", common.legend = T, widths = c(2, 1))
ggsave(here("figures/report21/invasion_heatmap.png"))
Saving 7.29 x 4.51 in image

#————————————-# # Effect of various cue perception #————————————-#
#——————————-# # static #——————————-# # logging
combined
static_comb.df <- left_join(
select(static_nocomb, cue_1, label_ci_2, log_1, Self = fitness_diff),
select(static_comb, cue_1, label_ci_2, log_1, fTotal = fitness_diff),
by = c("cue_1", "log_1", "label_ci_2")) %>%
filter(!is.na(Total) & !is.na(Self)) %>%
mutate(classification = ifelse(Total > Self, "Total better", "Self better"))
Error in `h()`:
! Problem with `filter()` input `..1`.
ℹ Input `..1` is `!is.na(Total) & !is.na(Self)`.
x object 'Total' not found
Backtrace:
1. ... %>% ...
8. base::.handleSimpleError(...)
9. dplyr h(simpleError(msg, call))
plot

#——————————–# # invasion #——————————–#
# join invade df with label because I am lazy
invade.df2 <- invade.df %>%
left_join(select(ez_label, id_ci, label_ci_1 = label_ci), by = c("mut_id" = "id_ci"))
log
# get non-logged pairings
invade_nolog <- invade.df2 %>%
mutate(cue_1 = trimws(gsub("\\ .*", "", label_ci_1)),
log_1 = case_when(
str_detect(label_ci_1, "log") ~ "log",
str_detect(label_ci_1, "log", negate = T) ~ "none")) %>%
filter(log_1 == "none")
invade_log <- invade.df2 %>%
mutate(cue_1 = trimws(gsub("\\ .*", "", label_ci_1)),
log_1 = case_when(
str_detect(label_ci_1, "log") ~ "log",
str_detect(label_ci_1, "log", negate = T) ~ "none")) %>%
filter(log_1 == "log")
invade_log.df <- left_join(
select(invade_nolog, cue_1, res_id, log_1, None = fitness),
select(invade_log, cue_1, res_id, log_1, Log = fitness),
by = c("cue_1", "res_id")) %>%
filter(!is.na(None) & !is.na(Log)) %>%
mutate(classification = ifelse(Log > None, "Logged better", "Not logged better"))
combined
invade_nocomb <- invade.df2 %>%
mutate(cue_1 = ifelse(
str_detect(label_ci_1, "sum"), "I+Ig",
trimws(gsub("+1.*|\\ log", "", label_ci_1))
),
log_1 = case_when(
str_detect(label_ci_1, "log") ~ "log",
str_detect(label_ci_1, "log", negate = T) ~ "none"),
comb_1 = case_when(
str_detect(label_ci_1, "1+|sum") ~ "comb",
str_detect(label_ci_1, "1+|sum", negate = T) ~ "none"
)) %>%
filter(comb_1 == "none")
invade_comb <- invade.df2 %>%
mutate(cue_1 = ifelse(
str_detect(label_ci_1, "sum"), "I+Ig",
trimws(gsub("+1.*|\\ log", "", label_ci_1))
),
log_1 = case_when(
str_detect(label_ci_1, "log") ~ "log",
str_detect(label_ci_1, "log", negate = T) ~ "none"),
comb_1 = case_when(
str_detect(label_ci_1, "1+|sum") ~ "comb",
str_detect(label_ci_1, "1+|sum", negate = T) ~ "none"
)) %>%
filter(comb_1 == "comb")
invade_comb.df <- left_join(
select(invade_nocomb, cue_1, res_id, log_1, Self = fitness),
select(invade_comb, cue_1, res_id, log_1, Total = fitness),
by = c("cue_1", "log_1", "res_id")) %>%
filter(!is.na(Total) & !is.na(Self)) %>%
mutate(classification = ifelse(Total > Self, "Total better", "Self better"))
plot. nevermind just assemble in illustrator
invade_cue.pl <- ggarrange(invade_log.pl, invade_comb.pl, align = "h", ncol = 2)
ggsave(here("figures/report21/invade_cue.png"))
Saving 7 x 7 in image
#——————————–# # arrange co-infection figure #——————————–#
ggarrange(static.pl, static_cue.pl, invasion.pl, invade_cue.pl, widths = c(1.5, 1), align = "hv", labels = c("A", "", "B", ""))
ggsave(here("figures/report21/coinfection_final.png"), width = 15, height = 12)
#———————————–# # organization dual cue optimization data #————————————#
check if fitness of the dual cue is better than individual. 17 out of 25 comparisons have lower fitness lol when optimized via dual cue. Not sure what could remedy this. Smaller cue steps?
dual cue improved the fitness of the following combination. note many of these comparisons are made when time steps are different. Need to modify optimization so that time scale is the same. We should also be comparing fitness at 30 days when full resolution is achieved.
- G_log and I_log
- G_none, I_log
- Ig_log and I_log
- Ig_none, I_log
- R_log, I_log
- R_none, I_log
- R_none, Ig_none
I_log is a reaccuring theme here.
dual_cue.df2 %>%
left_join(select(si_opt.df, id, fitness_si = fitness_20), by = c("id" = "id")) %>%
left_join(select(si_opt.df, id, fitness_si_b = fitness_20), by = c("id_b" = "id")) %>%
mutate(fitness_diff = fitness - fitness_si,
fitness_diff_b = fitness - fitness_si_b) %>%
filter(fitness_diff > 0 & fitness_diff_b > 0)
plotting out some interesting heatmaps
source(here("functions/par_to_hm.R"))
# G log and I log
par_to_hm(par = c(-0.535568221, -2.5019109, 5.3812132, 1.8928449, 0.23451243),
cue_range = seq(0, 4.77815125, length.out = 500),
cue_range_b = seq(0, 6.77815125, length.out = 500),
plot = T)

# Ig_log and I_log
par_to_hm(par = c(-0.253533013, -3.1078035, 7.8203134, 0.3603524, -3.51389462),
cue_range = seq(0, 6.77815125, length.out = 500),
cue_range_b = seq(0, 6.77815125,length.out = 500),
plot = T)

dual_cue.df2
# R_log, I_log
par_to_hm(par = c(5.249264033 ,8.9174937, -52.6281549 ,-21.1288712, -13.05080084),
cue_range = seq(6, 7, length.out = 500),
cue_range_b = seq(0, 6.77815125,length.out = 500),
plot = T)
NA

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKRXhwbG9yaW5nIGR1YWwtY3VlIGFwcHJvYWNoCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShkZVNvbHZlKQpsaWJyYXJ5KGNyb25lKQpsaWJyYXJ5KG9wdGltUGFyYWxsZWwpCmxpYnJhcnkoZG9QYXJhbGxlbCkKbGlicmFyeShkb1JORykKbGlicmFyeShhcnJvdykKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHBhcmFsbGVsKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShtaWNyb2JlbmNobWFyaykKbGlicmFyeShwcm9mdmlzKQpsaWJyYXJ5KFJBTk4pCmBgYAoKYGBge3J9CnBhcmFtZXRlcnNfdHN1a3VzaGkgPC0gYyhSMSA9IDguODkqKDEwXjYpLCAjIHNsaWdodGx5IGhpZ2hlcgogICAgICAgICAgICAgICAgbGFtYmRhID0gMy43KigxMF41KSwKICAgICAgICAgICAgICAgIG11ID0gMC4wMjUsIAogICAgICAgICAgICAgICAgcCA9IDgqKDEwXi02KSwgIyBkb3VibGVkIGZvcm0gb3JpZ2luYWwKICAgICAgICAgICAgICAgIGFscGhhID0gMSwgCiAgICAgICAgICAgICAgICBhbHBoYWcgPSAyLCAKICAgICAgICAgICAgICAgIGJldGEgPSA1LjcyMSwgCiAgICAgICAgICAgICAgICBtdW0gPSA0OCwgCiAgICAgICAgICAgICAgICBtdWcgPSA0LCAKICAgICAgICAgICAgICAgIEkwID0gNDMuODU5NjUsIAogICAgICAgICAgICAgICAgSWcwID0gMCwgCiAgICAgICAgICAgICAgICBhID0gMTUwLCAKICAgICAgICAgICAgICAgIGIgPSAxMDAsIAogICAgICAgICAgICAgICAgc3AgPSAxLAogICAgICAgICAgICAgICAgcHNpbiA9IDE2LjY5MjM0LAogICAgICAgICAgICAgICAgcHNpdyA9IDAuODQzMTc4NSwKICAgICAgICAgICAgICAgIHBoaW4gPSAwLjAzNTIwNTkxLCAKICAgICAgICAgICAgICAgIHBoaXcgPSA1NTAuODQyLAogICAgICAgICAgICAgICAgaW90YSA9IDIuMTgqKDEwXjYpLAogICAgICAgICAgICAgICAgcmhvID0gMC4yNjI3MTU2KQoKSV9yYW5nZV9ub25lIDwtIHNlcSgwLCA2KigxMF42KSwgYnkgPSAoNiooMTBeNikpLzUwMCkKSV9yYW5nZV9sb2cgPC0gc2VxKDAsIGxvZzEwKDYqKDEwXjYpKSwgYnkgPSAobG9nMTAoNiooMTBeNikpKS81MDApCkdfcmFuZ2Vfbm9uZSA8LSBzZXEoMCwgNiooMTBeNCksIGJ5ID0gKDYqKDEwXjQpKS81MDApCkdfcmFuZ2VfbG9nIDwtIHNlcSgwLCBsb2cxMCg2KigxMF40KSksIGJ5ID0gKGxvZzEwKDYqKDEwXjQpKSkvNTAwKQpgYGAKCiMgdGVzdGluZyBvdXQgbWdjdiBkdWFsIGN1ZSBzcGxpbmUgc3VyZmFjZS4gbG9va3MgZ29vZC4KIyMgbm90ZSB0aGF0IGlmIHdlIGdvIHdpdGggdGksIHRoYW4gd2UgaGF2ZSBvbmx5IGludGVyYWN0aW9ucyBiZXR3ZWVuIHRoZSAyIGN1ZXMgd2hlcmVhcyB0ZSBpbmNsdWRlcyBib3RoIG1haW4gZWZmZWN0IGFuZCBpbnRlcmFjdGlvbi4gdGkgZ2l2ZXMgdXMgNSBwYXJhbWV0ZXJzIHRvIG9wdGltemUgd2hlcmVhcyB0ZSBnaXZlcyB1cyA5LiBXZSBzaG91bGQgY29tcGFyZSB0aGUgdHdvCmBgYHtyfQpzb3VyY2UoaGVyZSgiZnVuY3Rpb25zL2NoYWJhdWRpX3NpX2NsZWFuLlIiKSkKCiMgc21hbGxlciBkaXZpc2lvbgpjdWVfcmFuZ2UgPC0gc2VxKDAsIDYqKDEwXjYpLCBieSA9ICg2KigxMF42KSkvNTAwKQpjdWVfcmFuZ2VfYiA8LSBzZXEoMCwgNiooMTBeNCksIGJ5ID0gKDYqKDEwXjQpKS81MDApCnBhcmFtZXRlcnNfY3IgPC0gcmVwKC0wLjUsOSkKCmNyX2dyaWQgPC0gZXhwYW5kLmdyaWQoY3VlX3JhbmdlLCBjdWVfcmFuZ2VfYikKICAgICMjIHJlbmFtZQogICAgbmFtZXMoY3JfZ3JpZCkgPC0gYygiY3VlX3JhbmdlIiwgImN1ZV9yYW5nZV9iIikKICAgICMjIGNyZWF0ZSBkdW1teSB5CiAgICBkdW1teV95IDwtIHJ1bmlmKGxlbmd0aChjdWVfcmFuZ2VfYiksIDAsIDEpCiAgICAjIyBwdXQgdG9nZXRoZXIgZGYKICAgIGR1bW15X2RmIDwtIGRhdGEuZnJhbWUoY3VlX3JhbmdlLCBjdWVfcmFuZ2VfYiwgZHVtbXlfeSkKICAgICMjIGdhbSBtb2RlbAogICAgZHVtbXlfY3IubW9kIDwtIG1nY3Y6OmdhbShkdW1teV95IH4gdGUoY3VlX3JhbmdlLCBjdWVfcmFuZ2VfYiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicyA9IGMoInRwIiwgInRwIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsgPSBjKDMsMykpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGR1bW15X2RmLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIlJFTUwiKQogICAgIyMgYXNzaWduIHBhcmFtZXRlcnMKICAgIGR1bW15X2NyLm1vZCRjb2VmZmljaWVudHMgPC0gcGFyYW1ldGVyc19jcgogICAgCiAgICAjIGV4cG9uZW50aWFsIHRyYW5zZm9ybWF0aW9uIHRvIGxpbWl0IGNvbnZlcnNpb24gcmF0ZSB0byBiZXR3ZWVuIDAgYW5kIDEKICAgIGNyX2Z1biA8LSBmdW5jdGlvbihjdWVfMSwgY3VlXzIpewogICAgICByZXMgPC0gZXhwKC1leHAobWdjdjo6cHJlZGljdC5nYW0oZHVtbXlfY3IubW9kLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBkYXRhLmZyYW1lKCJjdWVfcmFuZ2UiID0gY3VlXzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY3VlX3JhbmdlX2IiID0gY3VlXzIpKSkpCiAgICAgIHJldHVybihyZXMpCiAgICB9CiAgICAKCmBgYAoKCgojIGN1dHRpbmcgZG93biBjb21wdXRhdGlvbmFsIHRpbWUKYGBge3J9CnNvdXJjZShoZXJlKCJmdW5jdGlvbnMvY2hhYmF1ZGlfc2lfY2xlYW4uUiIpKQpzb3VyY2UoaGVyZSgiZnVuY3Rpb25zL3Rlc3QuUiIpKQoKIyBlYWNoIHJ1biB0YWtlcyBhcm91bmQgMSBtaW51dGUgKGNyX2Z1bikgKDEwMCBkaXZpc2lvbnMpCiMgc3dpdGNoaW5nIHRvIG5uMiB0YWtlcyAxNDUgc2Vjb25kcwojIGluY3JlYXNpbmcgZGl2aXNvbnMgdG8gNTAwIHVzaW5nIHByZWRpY3QuZ2FtIHRha2VzIHN0aWxsIGFyb3VuZCA1NyBzZWNvbmRzLiBTbyBpbmNyZWFzaW5nIHRvIDUwMCBkb2Vzbid0IHNlZW0gbGlrZSBhIGJhZCBpZGVhCnN5c3RlbS50aW1lKHRlc3QocGFyYW1ldGVyc19jciA9IHJlcCgwLjUsIDUpLAogICAgICAgaW1tdW5pdHkgPSAidHN1a3VzaGkiLAogICAgICAgcGFyYW1ldGVycyA9IHBhcmFtZXRlcnNfdHN1a3VzaGksCiAgICAgICB0aW1lX3JhbmdlID0gc2VxKDAsIDIwLCAwLjAwMSksCiAgICAgICBjdWUgPSAiSSIsCiAgICAgICBjdWVfYiA9ICJHIiwKICAgICAgIGN1ZV9yYW5nZSA9IElfcmFuZ2VfbG9nLAogICAgICAgY3VlX3JhbmdlX2IgPSBHX3JhbmdlX2xvZywKICAgICAgIHNvbHZlciA9ICJ2b2RlIiwKICAgICAgIGxvZ19jdWUgPSAibG9nMTAiLAogICAgICAgbG9nX2N1ZV9iID0gImxvZzEwIgogICAgICAgKSkKCgpgYGAKCiMgbWFraW5nIHNoaXQgZ28gZmFzdCEgTmVlZCB0byBjdXQgZG93biBvbiB0aW1lIHRvIGdldCBjciBmcm9tIGZ1bmN0aW9uCmBgYHtyfQpjdWVfcmFuZ2UgPC0gSV9yYW5nZV9sb2cKY3VlX3JhbmdlX2IgPC0gR19yYW5nZV9sb2cKY3JfZ3JpZCA8LSBleHBhbmQuZ3JpZChjdWVfcmFuZ2UsIGN1ZV9yYW5nZV9iKQoKIyMgcmVuYW1lCm5hbWVzKGNyX2dyaWQpIDwtIGMoImN1ZV9yYW5nZSIsICJjdWVfcmFuZ2VfYiIpCiMjIGNyZWF0ZSBkdW1teSB5CmR1bW15X3kgPC0gcnVuaWYobGVuZ3RoKGN1ZV9yYW5nZV9iKSwgMCwgMSkKIyMgcHV0IHRvZ2V0aGVyIGRmCmR1bW15X2RmIDwtIGRhdGEuZnJhbWUoY3VlX3JhbmdlLCBjdWVfcmFuZ2VfYiwgZHVtbXlfeSkKIyMgZ2FtIG1vZGVsCmR1bW15X2NyLm1vZCA8LSBtZ2N2OjpiYW0oZHVtbXlfeSB+IHRpKGN1ZV9yYW5nZSwgY3VlX3JhbmdlX2IsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgayA9IGMoMywzKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZHVtbXlfZGYpCiMjIGFzc2lnbiBwYXJhbWV0ZXJzCmR1bW15X2NyLm1vZCRjb2VmZmljaWVudHMgPC0gcmVwKDAuNSw1KQogICAgCiMgb3JpZ2luYWwgZnVuY3Rpb24gb2YgZ2V0dGluZyBjcgpjcl9mdW4gPC0gZnVuY3Rpb24oY3VlXzEsIGN1ZV8yKXsKICAgICAgZXhwKC1leHAobWdjdjo6cHJlZGljdC5iYW0oZHVtbXlfY3IubW9kLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoImN1ZV9yYW5nZSIgPSBjdWVfMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjdWVfcmFuZ2VfYiIgPSBjdWVfMiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4udGhyZWFkcyA9IDMpKSkKICB9CiAgICAKCmNyX3JlcyA8LSBleHAoLWV4cChtZ2N2OjpwcmVkaWN0LmdhbShkdW1teV9jci5tb2QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IGNyX2dyaWQpKSkKY3JfZGYgPC0gY2JpbmQoY3JfZ3JpZCwgY3JfcmVzKQoKY3VlXzEgPC0gMQpjdWVfMiA8LSAwLjUKCiMgYW5vdGhlciBmdW5jdGlvbiBmb3IgbmVhcm5lc3QgbmVpZ2hvdWJycwpubl9mdW4gPC0gZnVuY3Rpb24oY3VlXzEsIGN1ZV8yKXsKICBjcl9kZltubjIoZGF0YT1jcl9ncmlkLCBxdWVyeSA9IGNiaW5kKGN1ZV8xLCBjdWVfMiksIGs9MSwgdHJlZXR5cGU9ICJrZCIsCiAgICAgICAgICAgIHNlYXJjaHR5cGUgPSAicHJpb3JpdHkiKVtbMV1dLDNdCn0KCm5uX2Z1bjIgPC0gZnVuY3Rpb24oY3VlXzEsIGN1ZV8yKXsKICBjcl9kZltGTk46OmtubnguaW5kZXgoZGF0YT1jcl9ncmlkLCBxdWVyeSA9IGNiaW5kKGN1ZV8xLCBjdWVfMiksIGsgPSAxLCBhbGdvcml0aG0gPSAia2RfdHJlZSIpLDNdCn0KCgojIHZlcnkgc2ltaWxhcgpjcl9mdW4oMSwxKQpubl9mdW4oMSwxKQpubl9mdW4yKDEsMSkKCiMgZ2FtLnByZWRpY3QgaXMgZmFzdGVyCm1pY3JvYmVuY2htYXJrKGNyX2Z1bigxLDEpKQptaWNyb2JlbmNobWFyayhubl9mdW4oMSwxKSkKbWljcm9iZW5jaG1hcmsobm5fZnVuMigxLDEpKQpgYGAKIyBzYW5pdHkgY2hlY2t6CmBgYHtyfQpzb3VyY2UoaGVyZSgiZnVuY3Rpb25zL3Rlc3QuUiIpKQojIHN3aXRjaGluZyBiZXR3ZWVuIGN1ZSBhbmQgY3VlX2IuIHNob3VsZCBub3QgbWFrZSBhIGRpZmZlcmVuY2UKIyA0LjQ2OTA2Nwp0ZXN0KHBhcmFtZXRlcnNfY3IgPSByZXAoMC41LCA1KSwKICAgICAgIGltbXVuaXR5ID0gInRzdWt1c2hpIiwKICAgICAgIHBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJzX3RzdWt1c2hpLAogICAgICAgdGltZV9yYW5nZSA9IHNlcSgwLCAyMCwgMC4wMSksCiAgICAgICBjdWUgPSAiSSIsCiAgICAgICBjdWVfYiA9ICJHIiwKICAgICAgIGN1ZV9yYW5nZSA9IElfcmFuZ2VfbG9nLAogICAgICAgY3VlX3JhbmdlX2IgPSBHX3JhbmdlX2xvZywKICAgICAgIHNvbHZlciA9ICJ2b2RlIiwKICAgICAgIGxvZ19jdWUgPSAibG9nMTAiLAogICAgICAgbG9nX2N1ZV9iID0gImxvZzEwIgogICAgICAgKQoKIyA0LjQ2OTA2Ni4gZ29vZAp0ZXN0KHBhcmFtZXRlcnNfY3IgPSByZXAoMC41LCA1KSwKICAgICAgIGltbXVuaXR5ID0gInRzdWt1c2hpIiwKICAgICAgIHBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJzX3RzdWt1c2hpLAogICAgICAgdGltZV9yYW5nZSA9IHNlcSgwLCAyMCwgMC4wMSksCiAgICAgICBjdWUgPSAiRyIsCiAgICAgICBjdWVfYiA9ICJJIiwKICAgICAgIGN1ZV9yYW5nZSA9IEdfcmFuZ2VfbG9nLAogICAgICAgY3VlX3JhbmdlX2IgPSBJX3JhbmdlX2xvZywKICAgICAgIHNvbHZlciA9ICJ2b2RlIiwKICAgICAgIGxvZ19jdWUgPSAibG9nMTAiLAogICAgICAgbG9nX2N1ZV9iID0gImxvZzEwIgogICAgICAgKQoKIyBzaG9ydCB0aW1lIHN0ZXBzIHZzIGxvbmdlciB0aW1lIHN0ZXBzLiBiYXJlbHkgbWFkZSBhIGRpZmZlcmVuY2UKIyA0LjQ2OTA0CnRlc3QocGFyYW1ldGVyc19jciA9IHJlcCgwLjUsIDUpLAogICAgICAgaW1tdW5pdHkgPSAidHN1a3VzaGkiLAogICAgICAgcGFyYW1ldGVycyA9IHBhcmFtZXRlcnNfdHN1a3VzaGksCiAgICAgICB0aW1lX3JhbmdlID0gc2VxKDAsIDIwLCAwLjAwMSksCiAgICAgICBjdWUgPSAiSSIsCiAgICAgICBjdWVfYiA9ICJHIiwKICAgICAgIGN1ZV9yYW5nZSA9IElfcmFuZ2VfbG9nLAogICAgICAgY3VlX3JhbmdlX2IgPSBHX3JhbmdlX2xvZywKICAgICAgIHNvbHZlciA9ICJ2b2RlIiwKICAgICAgIGxvZ19jdWUgPSAibG9nMTAiLAogICAgICAgbG9nX2N1ZV9iID0gImxvZzEwIgogICAgICAgKQoKIyBjaGFuZ2luZyBsb2dzIG9uIGN1ZV9iCiMgNi4yMDYzOQp0ZXN0KHBhcmFtZXRlcnNfY3IgPSByZXAoMC41LCA1KSwKICAgICAgIGltbXVuaXR5ID0gInRzdWt1c2hpIiwKICAgICAgIHBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJzX3RzdWt1c2hpLAogICAgICAgdGltZV9yYW5nZSA9IHNlcSgwLCAyMCwgMC4wMSksCiAgICAgICBjdWUgPSAiSSIsCiAgICAgICBjdWVfYiA9ICJHIiwKICAgICAgIGN1ZV9yYW5nZSA9IElfcmFuZ2VfbG9nLAogICAgICAgY3VlX3JhbmdlX2IgPSBHX3JhbmdlX25vbmUsCiAgICAgICBzb2x2ZXIgPSAidm9kZSIsCiAgICAgICBsb2dfY3VlID0gImxvZzEwIiwKICAgICAgIGxvZ19jdWVfYiA9ICJub25lIgogICAgICAgKQoKIyBjaGFuZ2luZyBsb2dzIG9uIGN1ZQojIDUuMTEwODczCnRlc3QocGFyYW1ldGVyc19jciA9IHJlcCgwLjUsIDUpLAogICAgICAgaW1tdW5pdHkgPSAidHN1a3VzaGkiLAogICAgICAgcGFyYW1ldGVycyA9IHBhcmFtZXRlcnNfdHN1a3VzaGksCiAgICAgICB0aW1lX3JhbmdlID0gc2VxKDAsIDIwLCAwLjAxKSwKICAgICAgIGN1ZSA9ICJJIiwKICAgICAgIGN1ZV9iID0gIkciLAogICAgICAgY3VlX3JhbmdlID0gSV9yYW5nZV9ub25lLAogICAgICAgY3VlX3JhbmdlX2IgPSBHX3JhbmdlX2xvZywKICAgICAgIHNvbHZlciA9ICJ2b2RlIiwKICAgICAgIGxvZ19jdWUgPSAibm9uZSIsCiAgICAgICBsb2dfY3VlX2IgPSAibG9nMTAiCiAgICAgICApCgojIGNoZWNpbmcgc2luZ2xlIGN1ZSBpbmZlY3Rpb24uIHNhbWUgCiMjIDQuNzI0ODA0CnRlc3QocGFyYW1ldGVyc19jciA9IHJlcCgwLjUsIDQpLAogICAgICAgaW1tdW5pdHkgPSAidHN1a3VzaGkiLAogICAgICAgcGFyYW1ldGVycyA9IHBhcmFtZXRlcnNfdHN1a3VzaGksCiAgICAgICB0aW1lX3JhbmdlID0gc2VxKDAsIDIwLCAwLjAxKSwKICAgICAgIGN1ZSA9ICJJIiwKICAgICAgIGN1ZV9yYW5nZSA9IElfcmFuZ2Vfbm9uZSwKICAgICAgIHNvbHZlciA9ICJ2b2RlIiwKICAgICAgIGxvZ19jdWUgPSAibm9uZSIsCiAgICAgICApCiMgNC43MjQ4MDQKY2hhYmF1ZGlfc2lfY2xlYW4ocGFyYW1ldGVyc19jciA9IHJlcCgwLjUsIDQpLAogICAgICAgaW1tdW5pdHkgPSAidHN1a3VzaGkiLAogICAgICAgcGFyYW1ldGVycyA9IHBhcmFtZXRlcnNfdHN1a3VzaGksCiAgICAgICB0aW1lX3JhbmdlID0gc2VxKDAsIDIwLCAwLjAxKSwKICAgICAgIGN1ZSA9ICJJIiwKICAgICAgIGN1ZV9yYW5nZSA9IElfcmFuZ2Vfbm9uZSwKICAgICAgIHNvbHZlciA9ICJ2b2RlIiwKICAgICAgIGxvZ19jdWUgPSAibm9uZSIsCiAgICAgICApCmBgYAoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojIHJlbWFraW5nIG9mIGNvLWluZmVjdGlvbiByZWFjdGlvbiBub3JtCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKYGBge3J9CnNvdXJjZShoZXJlKCJmdW5jdGlvbnMvY2hhYmF1ZGlfY2lfY2xlYW4uUiIpKQpzb3VyY2UoaGVyZSgiZnVuY3Rpb25zL3Bhcl90b19kZi5SIikpCmBgYAoKIyBmdW5jdGlvbiBmb3IgZ2V0dGluZyBjb252ZXJzaW9uIHJhdGUgcmVhY3Rpb24gbm9ybSBhbmQgZHluYW1pY3MKYGBge3J9CmdldF9jaV9keW4gPC0gZnVuY3Rpb24oZGYpewogIAogICMgZ2V0IGhlYXZpc2RlIHRyYW5zZm9ybWF0aW9uCiAgaGVhdmlzaWRlX3RyYW5zIDwtIGZ1bmN0aW9uKGN1ZV9yYW5nZSwgbWF4KXsKICAgIGNyb25lOjpoZWF2aXNpZGUoY3VlX3JhbmdlKSooY3VlX3JhbmdlKSsoY3JvbmU6OmhlYXZpc2lkZShjdWVfcmFuZ2UtbWF4KSoobWF4LWN1ZV9yYW5nZSkpCn0KICAKICAjIHJlYWQgaW4gZGYgaW5mbwogIGN1ZV8xIDwtIGlmZWxzZShzdHJpbmdyOjpzdHJfZGV0ZWN0KGRmJGN1ZSwgIi1pIiksIAogICAgICAgICAgICAgICAgICBnc3ViKCIqLWkiLCAiMSIsIGRmJGN1ZSksCiAgICAgICAgICAgICAgICAgIGRmJGN1ZSkKICAKICBjdWVfMiA8LSBpZmVsc2Uoc3RyaW5ncjo6c3RyX2RldGVjdChkZiRjdWUsICItaSIpLCAKICAgICAgICAgICAgICAgICAgZ3N1YigiKi1pIiwgIjIiLCBkZiRjdWUpLAogICAgICAgICAgICAgICAgICBkZiRjdWUpCiAgCiAgbG9nIDwtIGlmZWxzZShzdHJpbmdyOjpzdHJfZGV0ZWN0KGRmJGxvZywgImxvZyIpLAogICAgICAgICAgICAgICAgImxvZzEwIiwgIm5vbmUiKQogIAogICMgZ2V0IHBhcmFtZXRlcgogIHBhciA8LSBjKGRmJHZhcjEsIGRmJHZhcjIsIGRmJHZhcjMsIGRmJHZhcjQpCiAgY3VlX3JhbmdlIDwtIHNlcShkZiRsb3csIGRmJGhpZ2gsIGJ5ID0gZGYkYnkpCiAgbGFiZWwgPC0gZGYkbGFiZWwKICAKICAjIGdldCBkeW5hbWljcwogIGR5biA8LSBjaGFiYXVkaV9jaV9jbGVhbihwYXJhbWV0ZXJzX2NyXzEgPSBwYXIsCiAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcnNfY3JfMiA9IHBhciwKICAgICAgICAgICAgICAgICAgaW1tdW5pdHkgPSAidHN1a3VzaGkiLAogICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJzID0gcGFyYW1ldGVyc190c3VrdXNoaSwKICAgICAgICAgICAgICAgICAgY3VlXzEgPSBjdWVfMSwKICAgICAgICAgICAgICAgICAgY3VlXzIgPSBjdWVfMiwKICAgICAgICAgICAgICAgICAgY3VlX3JhbmdlXzEgPSBjdWVfcmFuZ2UsCiAgICAgICAgICAgICAgICAgIGN1ZV9yYW5nZV8yID0gY3VlX3JhbmdlLAogICAgICAgICAgICAgICAgICBsb2dfY3VlXzEgPSBsb2csCiAgICAgICAgICAgICAgICAgIGxvZ19jdWVfMiA9IGxvZywKICAgICAgICAgICAgICAgICAgc29sdmVyID0gInZvZGUiLAogICAgICAgICAgICAgICAgICB0aW1lX3JhbmdlID0gc2VxKDAsIDMwLCAwLjAwMSksCiAgICAgICAgICAgICAgICAgIGR5biA9IFQpCiAgCiAgICBkeW4yIDwtIGRhdGEuZnJhbWUoZHluLCBsYWJlbCA9IHJlcChsYWJlbCwgbnJvdyhkeW4pKSkKCiAgIyBnZXQgcmVhY3Rpb24gbm9ybQogIHJuIDwtIHBhcl90b19kZihwYXIgPSBwYXIsIGN1ZV9yYW5nZSA9IGN1ZV9yYW5nZSkKCiAgIyBnZXQgcnVnCiAgIyMgaWYgKyBpbiBjdWUsIG5lZWQgdG8gZmlsdGVyIG91dCB0aG9zZSB2YXJpYWJsZXMgYW5kIGFkZCB0b2dldGhlcgogIGlmKHN0cmluZ3I6OnN0cl9kZXRlY3QoY3VlXzEsICJcXCsiKSl7CiAgICBjdWVfc3BsaXQgPC0gc3RyaW5ncjo6c3RyX3NwbGl0KHN0cmluZyA9IGN1ZV8xLCBwYXR0ZXJuID0gIlxcKyIsIHNpbXBsaWZ5ID0gVCkKICAgICMjIGdldCB0aGUgdHdvIGN1ZXMgCiAgICBjdWVfdGVtcF8xIDwtIGN1ZV9zcGxpdFtbMV1dCiAgICBjdWVfdGVtcF8yIDwtIGN1ZV9zcGxpdFtbMl1dCiAgICAKICAgICMjIGZpbHRlciBkeW4KICAgIHJ1ZyA8LSBkeW4yICU+JSAKICAgICAgZmlsdGVyKHZhcmlhYmxlID09IGN1ZV90ZW1wXzEgfCB2YXJpYWJsZSA9PSBjdWVfdGVtcF8yKSAlPiUgCiAgICAgIGRwbHlyOjpncm91cF9ieSh0aW1lKSAlPiUgCiAgICAgIGRwbHlyOjptdXRhdGUoc3VtID0gc3VtKHZhbHVlKSkgJT4lIAogICAgICBzZWxlY3QodGltZSwgdmFsdWUgPSBzdW0sIGxhYmVsKQogIH0KICAKICAjIyBpZiBzdW0KICBpZihjdWVfMSA9PSAic3VtIil7CiAgICAjIyBmaWx0ZXIgZHluCiAgICBydWcgPC0gZHluMiAlPiUgCiAgICAgIGZpbHRlcih2YXJpYWJsZSA9PSAiSTEiIHwgdmFyaWFibGUgPT0gIkkyIiB8IHZhcmlhYmxlID09ICJJZzEiIHwgdmFyaWFibGUgPT0gIklnMiIpICU+JSAKICAgICAgZHBseXI6Omdyb3VwX2J5KHRpbWUpICU+JSAKICAgICAgZHBseXI6Om11dGF0ZShzdW0gPSBzdW0odmFsdWUpKSAlPiUgCiAgICAgIHNlbGVjdCh0aW1lLCB2YWx1ZSA9IHN1bSwgbGFiZWwpCiAgfQogIAogICMgZm9yIHNpbXBsaWZpZWQgY3VlCiAgaWYoc3RyaW5ncjo6c3RyX2RldGVjdChjdWVfMSwgIlxcKyIsIG5lZ2F0ZSA9IFQpICYmIGN1ZV8xICE9ICJzdW0iKXsKICAgIHJ1ZyA8LSBkeW4yICU+JSAKICAgICAgZHBseXI6OmZpbHRlcih2YXJpYWJsZSA9PSBjdWVfMSkgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHRpbWUsIHZhbHVlLCBsYWJlbCl9CiAgCiAgIyBmb3IgbG9nZ2VkLCBiYWNrdHJhbnNmb3JtIGN1ZSByYW5nZSBvZiByZWFjdGlvbiBub3JtIAogIHJuMiA8LSBybgogIAogIGlmKHN0cmluZ3I6OnN0cl9kZXRlY3QobG9nLCAibG9nIikpe3JuMiRjdWVfcmFuZ2UgPC0gMTBeKHJuMiRjdWVfcmFuZ2UpfQoKICAjIGFwcGVuZCBsYWJlbCB0byByZWFjdGlvbiBub3JtLCBkeW4sIGFuZCBydWcKICBybjIgPC0gZGF0YS5mcmFtZShybjIsIGxhYmVsID0gcmVwKGxhYmVsLCBucm93KHJuKSkpCgogIHJldHVybihsaXN0KGR5bjIsIHJuMiwgcnVnKSkKfQpgYGAKCiMgcmVhZCBpbiBjb19pbmZlY3Rpb24gb3B0CmBgYHtyfQpjaV9vcHQuZGYgPC0gcmVhZC5jc3YoaGVyZSgiZGF0YS9jaV9vcHQuY3N2IikpCmN1ZV9yYW5nZV9jaSA8LSByZWFkLmNzdihoZXJlKCJkYXRhL2N1ZV9yYW5nZV9jaS5jc3YiKSkKCiMgam9pbiB3aXRoIGN1ZSByYW5nZQpjaV9vcHQuZGYgPC0gY2lfb3B0LmRmICU+JSBsZWZ0X2pvaW4oc2VsZWN0KGN1ZV9yYW5nZV9jaSwgaWQsIGxvdywgaGlnaCwgYnkpLCBieSA9IGMoImlkIiA9ICJpZCIpKQoKIyBzcGxpdApjaV9vcHQubHMgPC0gc3BsaXQoY2lfb3B0LmRmLCBzZXEobnJvdyhjaV9vcHQuZGYpKSkKCiMgbG9vcApjaV9vcHQuZHluIDwtIGxhcHBseShjaV9vcHQubHMsIGdldF9jaV9keW4pCgojIGJpbmQgdG9nZXRoZXIgZHluYW1pY3MKZHluLmxzIDwtIGxhcHBseShjaV9vcHQuZHluLCBmdW5jdGlvbih4KXhbWzFdXSkKY2lfZHluLmRmIDwtIGRvLmNhbGwocmJpbmQsIGR5bi5scykKd3JpdGVfcGFycXVldChjaV9keW4uZGYsIGhlcmUoImRhdGEvY2lfZHluL2NpX2R5bi5wYXJxdWV0IikpCgpybi5scyA8LSBsYXBwbHkoY2lfb3B0LmR5biwgZnVuY3Rpb24oeCl4W1syXV0pCmNpX3JuLmRmIDwtIGRvLmNhbGwocmJpbmQsIHJuLmxzKQp3cml0ZV9wYXJxdWV0KGNpX3JuLmRmLCBoZXJlKCJkYXRhL2NpX2R5bi9jaV9ybi5wYXJxdWV0IikpCgpydWcubHMgPC0gbGFwcGx5KGNpX29wdC5keW4sIGZ1bmN0aW9uKHgpeFtbM11dKQpjaV9ydWcuZGYgPC0gZG8uY2FsbChyYmluZCwgcnVnLmxzKQp3cml0ZV9wYXJxdWV0KGNpX3J1Zy5kZiAsIGhlcmUoImRhdGEvY2lfZHluL2NpX3J1Zy5wYXJxdWV0IikpCmBgYAoKCgojIGdldCBpbiBzaW5nbGUgaW5mZWN0aW9uIHJlYWN0aW9uIG5vcm0gdG8gbWF0Y2gKYGBge3J9CnNpX29wdC5kZiA8LSByZWFkLmNzdihoZXJlKCJkYXRhL3NpX29wdC5jc3YiKSkKY3VlX3JhbmdlX3NpIDwtIHJlYWQuY3N2KGhlcmUoImRhdGEvY3VlX3JhbmdlX3NpLmNzdiIpKQoKc2lfb3B0LmRmIDwtIHNpX29wdC5kZiAlPiUgbGVmdF9qb2luKHNlbGVjdChjdWVfcmFuZ2Vfc2ksIGlkLCBsb3csIGhpZ2gsIGJ5LCBsYWJlbCksIGJ5ID0gImlkIikKCiMgZnVuY3Rpb24gdG8gZ2V0IHNpbmdsZSBpbmZlY3Rpb24gcmVhY3Rpb24gbm9ybQpnZXRfc2lfcm4gPC0gZnVuY3Rpb24oZGYpewogIHBhciA8LSBjKGRmJHZhcjEsIGRmJHZhcjIsIGRmJHZhcjMsIGRmJHZhcjQpCiAgY3VlX3JhbmdlIDwtIHNlcShkZiRsb3csIGRmJGhpZ2gsIGJ5ID0gZGYkYnkpCiAgCiAgcm4gPC0gcGFyX3RvX2RmKHBhciA9IHBhciwgY3VlX3JhbmdlID0gY3VlX3JhbmdlKQogIAogICMgZm9yIGxvZ2dlZCwgYmFja3RyYW5zZm9ybSBjdWUgcmFuZ2Ugb2YgcmVhY3Rpb24gbm9ybSAKICBybjIgPC0gcm4KICBpZihzdHJpbmdyOjpzdHJfZGV0ZWN0KGRmJGxvZywgImxvZyIpKXtybjIkY3VlX3JhbmdlIDwtIDEwXihybjIkY3VlX3JhbmdlKX0KCiAgIyBhcHBlbmQgbGFiZWwgdG8gcmVhY3Rpb24gbm9ybSwgZHluLCBhbmQgcnVnCiAgcm4yIDwtIGRhdGEuZnJhbWUocm4yLCBpZCA9IGRmJGlkLCBsYWJlbCA9IHJlcChkZiRsYWJlbCwgbnJvdyhybikpKQogIAogIHJldHVybihybjIpCn0KIyBybiBmdW5jdGlvbiBhbmQgYmluZCB0b2dldGhlcgpzaV9vcHQubHMgPC0gc3BsaXQoc2lfb3B0LmRmLCBzZXEobnJvdyhzaV9vcHQuZGYpKSkKc2lfb3B0LnJuIDwtIGxhcHBseShzaV9vcHQubHMsIGdldF9zaV9ybikKc2lfb3B0LnJuMiA8LSBkby5jYWxsKHJiaW5kLCBzaV9vcHQucm4pCgpgYGAKCiMgZ2V0IHNpbmdsZSBpbmZlY2l0b24gcnVnCmBgYHtyfQpzaV9keW4gPC0gcmVhZF9wYXJxdWV0KGhlcmUoImRhdGEvc2lfZHluL3NpX2R5bl8zMC5wYXJxdWV0IikpCgojIGpvaW4gdG8gZ2V0IGxhYmVsCnNpX2R5bi5kZiA8LSBsZWZ0X2pvaW4oc2lfZHluLCBzaV9vcHQuZGYsIGJ5ID0gImlkIikKCiMgcHJvY2VzcyBnZXQgcnVnCmdldF9ydWcgPC0gZnVuY3Rpb24oZGYpewogIGN1ZSA8LSB1bmlxdWUoZGYkY3VlKQogIAogICBpZihzdHJpbmdyOjpzdHJfZGV0ZWN0KGN1ZSwgIlxcKyIpKXsKICAgIGN1ZV9zcGxpdCA8LSBzdHJpbmdyOjpzdHJfc3BsaXQoc3RyaW5nID0gY3VlLCBwYXR0ZXJuID0gIlxcKyIsIHNpbXBsaWZ5ID0gVCkKICAgICMjIGdldCB0aGUgdHdvIGN1ZXMgCiAgICBjdWVfdGVtcF8xIDwtIGN1ZV9zcGxpdFtbMV1dCiAgICBjdWVfdGVtcF8yIDwtIGN1ZV9zcGxpdFtbMl1dCiAgICAjIyBmaWx0ZXIgZHluCiAgICBydWcgPC0gZGYgJT4lIAogICAgICBmaWx0ZXIodmFyaWFibGUgPT0gY3VlX3RlbXBfMSB8IHZhcmlhYmxlID09IGN1ZV90ZW1wXzIpICU+JSAKICAgICAgZHBseXI6Omdyb3VwX2J5KHRpbWUpICU+JSAKICAgICAgZHBseXI6Om11dGF0ZShzdW0gPSBzdW0odmFsdWUpKSAlPiUgCiAgICAgIHNlbGVjdCh0aW1lLCB2YWx1ZSA9IHN1bSwgbGFiZWwpCiAgfQogIAogICMgZm9yIHNpbXBsaWZpZWQgY3VlCiAgaWYoc3RyaW5ncjo6c3RyX2RldGVjdChjdWUsICJcXCsiLCBuZWdhdGUgPSBUKSl7CiAgICBydWcgPC0gZGYgJT4lIAogICAgICBkcGx5cjo6ZmlsdGVyKHZhcmlhYmxlID09IGN1ZSkgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHRpbWUsIHZhbHVlLCBsYWJlbCl9CiAgCiAgcmV0dXJuKHJ1ZykKfQoKIyBzcGxpdCBiYXNlZCBvbiBpbmRpdmlkdWFsIGxhYmVscwpzaV9keW4ubHMgPC0gc2lfZHluLmRmICU+JSBncm91cF9zcGxpdChpZCkKCiMgcnVuIGZ1bmN0aW9uIHRvIGdldCBydWcKc2lfcnVnIDwtIG1jbGFwcGx5KHNpX2R5bi5scywgZ2V0X3J1ZykKCnNpX3J1Zy5kZiA8LSBkby5jYWxsKHJiaW5kLCBzaV9ydWcpCmBgYAoKCiMgcHJvY2VzcyByZWFjdGlvbiBub3JtIGRhdGEgdG8gbGltaXQgcmVhY3Rpb24gbm9ybSB0byBhcm91bmQgdGhlIGluZmVjdGlvbiBzcGFjZQpgYGB7cn0KIyBnZXQgc2lfbGFiZWwgd2l0aCBjaSBjdWUgcmFuZ2UKc2lfY2lfcnVnLmRmIDwtIGNpX3J1Zy5kZiAlPiUgCiAgbXV0YXRlKGxhYmVsX3NpID0gY2FzZV93aGVuKAogICAgbGFiZWwgJWluJSBjKCJJIiwgIkkxK0kyIikgfiAiSSIsCiAgICBsYWJlbCAlaW4lIGMoIkkgbG9nIiwiSTErSTIgbG9nIikgfiAiSSBsb2ciLAogICAgbGFiZWwgJWluJSBjKCJJZyIsICJJZzErSWcyIikgfiAiSWciLAogICAgbGFiZWwgJWluJSBjKCJJZyBsb2ciKSB+ICJJZyBsb2ciLAogICAgbGFiZWwgJWluJSBjKCJzdW0iLCAiSStJZyIpIH4gIkkrSWciLAogICAgbGFiZWwgJWluJSBjKCJzdW0gbG9nIiwgIkkrSWcgbG9nIikgfiAiSStJZyBsb2ciLAogICAgbGFiZWwgPT0gIlIiIH4gIlIiLAogICAgbGFiZWwgPT0gIlIgbG9nIiB+ICJSIGxvZyIsCiAgICBsYWJlbCAlaW4lIGMoIkciLCAiRzErRzIiKSB+ICJHIiwKICAgIGxhYmVsID09ICJHIGxvZyIgfiAiRyBsb2ciCiAgKSkgCgojIGdldCBsaW1pdCBmb3Igc2lfcnVnCnNpX3J1Z19saW0uZGYgPC0gc2lfcnVnLmRmICU+JSAKICBncm91cF9ieShsYWJlbCklPiUgCiAgc3VtbWFyaXNlKG1pbiA9IG1pbih2YWx1ZSwgbmEucm0gPSBUKSowLjksCiAgICAgICAgIG1heCA9IG1heCh2YWx1ZSwgbmEucm0gPSBUKSoxLjEpICU+JSAKICBzZWxlY3QobGFiZWxfc2kgPSBsYWJlbCwgbWluX3NpID0gbWluLCBtYXhfc2kgPSBtYXgpCgoKIyBmaWx0ZXIgdG8gcmVzdHJpY3Rpb24gY29udmVyc2lvbiByYXRlIHJlYWN0aW9uIG5vcm0gcmFuZ2UgdG8gY3VlIHJhbmdlcyB0aGF0IGFwcGVhciBpbiBydWcKIyMgY2hhbmdlIHRvIEluZi8taW5mIHRvIE5BLiBOb3RlIHRoYXQgSSBhbSBmaXJzdCBqb2luaW5nIHdpdGggc2kgcnVnIGxpbSB0byBjaGVjayB3aGljaCBsaW1pdCBpcyBsYXJnZXIsIFdlIHdpbGwgZ28gd2l0aCB0aGUgY3VlIHJhbmdlIHRoYXQgaGFzIHRoZSBsYXJnZXN0IHNwYW4KY2lfcnVnX2xpbS5kZiA8LSBzaV9jaV9ydWcuZGYgJT4lIAogIGdyb3VwX2J5KGxhYmVsKSAlPiUgCiAgbXV0YXRlKG1pbiA9IG1pbih2YWx1ZSwgbmEucm0gPSBUKSowLjksCiAgICAgICAgIG1heCA9IG1heCh2YWx1ZSwgbmEucm0gPSBUKSoxLjEpICU+JSAKICBkaXN0aW5jdChsYWJlbCwgLmtlZXBfYWxsID0gVCkgJT4lIAogIHNlbGVjdChsYWJlbCwgbGFiZWxfc2ksIG1pbiwgbWF4KQoKcnVnX2xpbS5maW5hbCA8LSBjaV9ydWdfbGltLmRmICU+JSBsZWZ0X2pvaW4oc2lfcnVnX2xpbS5kZiwgYnkgPSAibGFiZWxfc2kiKSAlPiUgCiAgbXV0YXRlKGZpbmFsX21pbiA9IG1pbihtaW4sIG1pbl9zaSksCiAgICAgICAgIGZpbmFsX21heCA9IG1heChtYXgsIG1heF9zaSkpCgojIGZpbHRlciBjaV9ybiBieSBsaW1pdApjaV9ybl9saW0uZGYgPC0gY2lfcm4uZGYgJT4lIAogIGxlZnRfam9pbihydWdfbGltLmZpbmFsKSAlPiUgCiAgZ3JvdXBfYnkobGFiZWwpICU+JSAKICBmaWx0ZXIoY3VlX3JhbmdlIDw9IGZpbmFsX21heCAmIGN1ZV9yYW5nZSA+PSBmaW5hbF9taW4pCgpjaV9ybl9saW0uZGYgJT4lIGZpbHRlcihsYWJlbCA9PSAiRyBsb2ciKSAlPiUgZ2dwbG90KCkgKyBnZW9tX2xpbmUoYWVzKHggPSBjdWVfcmFuZ2UsIHkgPSBjcikpCmBgYAoKIyBtYXRjaCBzaW5nbGUgaW5mZWN0aW9uIHJuIHdpdGggY29pbmZlY3Rpb24gCmBgYHtyfQojIGdldCBjaSBsYWJlbCB0byBzaSBydWcgYW5kIGZpbHRlciBieSBsaW1pdApzaV9vcHQucm4zIDwtIHNlbGVjdChzaV9vcHQucm4yLCBjdWVfcmFuZ2UsIGNyLCBsYWJlbF9zaSA9IGxhYmVsKSAlPiUgCiAgbGVmdF9qb2luKGRpc3RpbmN0KHNlbGVjdChzaV9jaV9ydWcuZGYsIGxhYmVsLCBsYWJlbF9zaSksIGxhYmVsLCAua2VlcF9hbGwgPSBUKSwgYnkgPSAibGFiZWxfc2kiKSAlPiUgCiAgbGVmdF9qb2luKHJ1Z19saW0uZmluYWwpICU+JSAKICBncm91cF9ieShsYWJlbCkgJT4lIAogIGZpbHRlcihjdWVfcmFuZ2UgPD0gZmluYWxfbWF4ICYgY3VlX3JhbmdlID49IGZpbmFsX21pbikgJT4lIAogIHNlbGVjdChjdWVfcmFuZ2UsIGNyLCBsYWJlbCwgbGFiZWxfc2kpCgpzaV9vcHQucm4zCiMgZ2V0IGNpIGxhYmVsIHRvIHNpIHJ1ZwpzaV9ydWcuZGYyIDwtIHNlbGVjdChzaV9ydWcuZGYsIHZhbHVlLCBsYWJlbF9zaSA9IGxhYmVsKSAlPiUgCiAgbGVmdF9qb2luKGRpc3RpbmN0KHNlbGVjdChzaV9jaV9ydWcuZGYsIGxhYmVsLCBsYWJlbF9zaSksIGxhYmVsLCAua2VlcF9hbGwgPSBUKSwgYnkgPSAibGFiZWxfc2kiKQpgYGAKCiMgcGxvdCByZWFjdGlvbiBub3JtCmBgYHtyfQojIHJlb3JkZXIgdGhlIGN1ZXMgYW5kIGdldCBwcm9wZXIgbGFiZWxzCmV6X2xhYmVsIDwtIGNiaW5kLmRhdGEuZnJhbWUoCiAgaWRfY2kgPSBjKCJJLWlfbm9uZSIsICJJLWlfbG9nIiwKICAgICAgICAgICAgIkkxK0kyX25vbmUiLCAiSTErSTJfbG9nIiwKICAgICAgICAgICAgIklnLWlfbm9uZSIsICJJZy1pX2xvZyIsCiAgICAgICAgICAgICJJLWkrSWctaV9ub25lIiwgIkktaStJZy1pX2xvZyIsCiAgICAgICAgICAgICJzdW1fbm9uZSIsICJzdW1fbG9nIiwKICAgICAgICAgICAgIkctaV9ub25lIiwgIkctaV9sb2ciLAogICAgICAgICAgICAiRzErRzJfbm9uZSIsICJJZzErSWcyX25vbmUiLAogICAgICAgICAgICAiUl9ub25lIiwgIlJfbG9nIiksCiAgaWRfc2kgPSBjKCJJX25vbmUiLCAiSV9sb2ciLAogICAgICAgICAgICAiSV9ub25lIiwgIklfbG9nIiwKICAgICAgICAgICAgIklnX25vbmUiLCAiSWdfbG9nIiwKICAgICAgICAgICAgIkkrSWdfbm9uZSIsICJJK0lnX2xvZyIsCiAgICAgICAgICAgICJJK0lnX25vbmUiLCAiSStJZ19sb2ciLAogICAgICAgICAgICAiR19ub25lIiwgIkdfbG9nIiwKICAgICAgICAgICAgIkdfbm9uZSIsICJJZ19ub25lIiwKICAgICAgICAgICAgIlJfbm9uZSIsICJSX2xvZyIpLAogIGxhYmVsX2NpID0gYygiSSIsICJJIGxvZyIsCiAgICAgICAgICAgICJJMStJMiIsICJJMStJMiBsb2ciLAogICAgICAgICAgICAiSWciLCAiSWcgbG9nIiwKICAgICAgICAgICAgIkkrSWciLCAiSStJZyBsb2ciLAogICAgICAgICAgICAic3VtIiwgInN1bSBsb2ciLAogICAgICAgICAgICAiRyIsICJHIGxvZyIsCiAgICAgICAgICAgICJHMStHMiIsICJJZzErSWcyIiwKICAgICAgICAgICAgIlIiLCAiUiBsb2ciKSwKICBsYWJlbF9zaSA9IGMoIkkiLCAiSSBsb2ciLAogICAgICAgICAgICAgICAiSSIsICJJIGxvZyIsCiAgICAgICAgICAgICAgICJJZyIsICJJZyBsb2ciLAogICAgICAgICAgICAgICAiSStJZyIsICJJK0lnIGxvZyIsCiAgICAgICAgICAgICAgICJJK0lnIiwgIkkrSWcgbG9nIiwKICAgICAgICAgICAgICAgIkciLCAiRyBsb2ciLAogICAgICAgICAgICAgICAiRyIsICJJZyIsCiAgICAgICAgICAgICAgICJSIiwgIlIgbG9nIiksCiAgZXpfbGFiZWwgPSBjKCJBc2V4dWFsIGlSQkMiLCAiQXNleHVhbCBpUkJDIGxvZzEwIiwKICAgICAgICAgICAgICAgIlRvdGFsIGFzZXh1YWwgaVJCQyIsICJUb3RhbCBhc2V4dWFsXG5pUkJDIGxvZzEwIiwKICAgICAgICAgICAgICAgIlNleHVhbCBpUkJDIiwgIlNleHVhbCBpUkJDIGxvZzEwIiwKICAgICAgICAgICAgICAgIkFzZXh1YWwmc2V4dWFsIGlSQkMiLCAiQXNleHVhbCZzZXh1YWxcbmlSQkMgbG9nMTAiLAogICAgICAgICAgICAgICAiVG90YWwgaVJCQyIsICJUb3RhbCBpUkJDIGxvZzEwIiwKICAgICAgICAgICAgICAgIkdhbWV0b2N5dGUiLCAiR2FtZXRvY3l0ZSBsb2cxMCIsCiAgICAgICAgICAgICAgICJUb3RhbCBnYW1ldG9jeXRlIiwgIlRvdGFsIHNleHVhbCBpUkJDIiwKICAgICAgICAgICAgICAgIlJCQyIsICJSQkMgbG9nMTAiKSwKICBlel9sYWJlbF9zaSA9IGMoIkFzZXh1YWwgaVJCQyIsICJBc2V4dWFsIGlSQkMgbG9nMTAiLAogICAgICAgICAgICAgICAiQXNleHVhbCBpUkJDIiwgIkFzZXh1YWwgaVJCQyBsb2cxMCIsCiAgICAgICAgICAgICAgICJTZXh1YWwgaVJCQyIsICJTZXh1YWwgaVJCQyBsb2cxMCIsCiAgICAgICAgICAgICAgICJBc2V4dWFsJnNleHVhbCBpUkJDIiwgIkFzZXh1YWwmc2V4dWFsXG5pUkJDIGxvZzEwIiwKICAgICAgICAgICAgICAgIkFzZXh1YWwmc2V4dWFsIGlSQkMiLCAiQXNleHVhbCZzZXh1YWxcbmlSQkMgbG9nMTAiLAogICAgICAgICAgICAgICAiR2FtZXRvY3l0ZSIsICJHYW1ldG9jeXRlIGxvZzEwIiwKICAgICAgICAgICAgICAgIkdhbWV0b2N5dGUiLCAiU2V4dWFsIGlSQkMiLAogICAgICAgICAgICAgICAiUkJDIiwgIlJCQyBsb2cxMCIpCikKCndyaXRlLmNzdihlel9sYWJlbCwgaGVyZSgiZGF0YS9lel9sYWJlbC5jc3YiKSkKCiMgam9pbiB3aXRoIGV6bGFiZWwKY2lfcm5fbGltLmRmIDwtIGNpX3JuX2xpbS5kZiAlPiUgbGVmdF9qb2luKGV6X2xhYmVsKQpzaV9vcHQucm4zIDwtIHNpX29wdC5ybjMgJT4lIGxlZnRfam9pbihlel9sYWJlbCkKY2lfcnVnLmRmIDwtIGNpX3J1Zy5kZiAlPiUgbGVmdF9qb2luKGV6X2xhYmVsKQpzaV9ydWcuZGYyIDwtIHNpX3J1Zy5kZjIgJT4lIGxlZnRfam9pbihlel9sYWJlbCkKCiMgcmVkbyBvcmRlciBvZiBjdWVzCmNpX3JuX2xpbS5kZiRsYWJlbCA8LSBmYWN0b3IoY2lfcm5fbGltLmRmJGxhYmVsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiSSIsICJJIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkkxK0kyIiwgIkkxK0kyIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklnIiwgIklnIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkkrSWciLCAiSStJZyBsb2ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzdW0iLCAic3VtIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkciLCAiRyBsb2ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHMStHMiIsICJJZzErSWcyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUiIsICJSIGxvZyIpKSAKCnNpX29wdC5ybjMkbGFiZWwgPC0gZmFjdG9yKHNpX29wdC5ybjMkbGFiZWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJJIiwgIkkgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSTErSTIiLCAiSTErSTIgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSWciLCAiSWcgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSStJZyIsICJJK0lnIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN1bSIsICJzdW0gbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRyIsICJHIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkcxK0cyIiwgIklnMStJZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSIiwgIlIgbG9nIikpCgpjaV9ydWcuZGYkbGFiZWwgPC0gZmFjdG9yKGNpX3J1Zy5kZiRsYWJlbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkkiLCAiSSBsb2ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJMStJMiIsICJJMStJMiBsb2ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJZyIsICJJZyBsb2ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJK0lnIiwgIkkrSWcgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3VtIiwgInN1bSBsb2ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHIiwgIkcgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRzErRzIiLCAiSWcxK0lnMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlIiLCAiUiBsb2ciKSkKCnNpX3J1Zy5kZjIkbGFiZWwgPC0gZmFjdG9yKHNpX3J1Zy5kZjIkbGFiZWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJJIiwgIkkgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSTErSTIiLCAiSTErSTIgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSWciLCAiSWcgbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSStJZyIsICJJK0lnIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN1bSIsICJzdW0gbG9nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRyIsICJHIGxvZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkcxK0cyIiwgIklnMStJZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSIiwgIlIgbG9nIikpCgojIHBsb3QKb3B0X2N1ZV9wbC5BIDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IGNpX3JuX2xpbS5kZiwgYWVzKHggPSBjdWVfcmFuZ2UsIHkgPSBjciwgY29sb3IgPSAiQ28taW5mZWN0aW9uIikpICsKICBnZW9tX2xpbmUoZGF0YSA9IHNpX29wdC5ybjMsIGFlcyh4ID0gY3VlX3JhbmdlLCB5ID0gY3IsIGNvbG9yID0gIlNpbmdsZSBpbmZlY3Rpb24iKSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fcnVnKGRhdGEgPSBjaV9ydWcuZGYsIGFlcyh4ID0gdmFsdWUpLCBjb2xvciA9ICIjNDU3NWI0Iiwgc2lkZXMgPSAidCIpICsKICBnZW9tX3J1ZyhkYXRhID0gc2lfcnVnLmRmMiwgYWVzKHggPSB2YWx1ZSksIGNvbG9yID0gIiNmYzhkNTkiLCBzaWRlcyA9ICJiIikgKwogIGZhY2V0X3dyYXAofmV6X2xhYmVsLCBzY2FsZXMgPSAiZnJlZV94IiwgbmNvbCA9IDIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHkgPSAiQ29udmVyc2lvbiByYXRlIiwgeCA9ICJDdWUgcmFuZ2UiLCBjb2xvciA9ICJJbmZlY3Rpb24iKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIGZvcm1hdCh4LCBzY2llbnRpZmljID0gVCksCiAgICAgICAgICAgICAgICAgICAgIGd1aWRlID0gZ3VpZGVfYXhpcyhjaGVjay5vdmVybGFwID0gVFJVRSkpICsgCiAgICAgICAgICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKSAgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyggIiM0NTc1YjQiLCAiI2ZjOGQ1OSIpKQoKZ2dzYXZlKGhlcmUoImZpZ3VyZXMvcmVwb3J0MjEvcmVhY3Rpb25fbm9ybS5wbmciKSwgd2lkdGggPSA3LCBoZWlnaHQgPSAxMCkKCmBgYAoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojIHBsb3QgbWF4aW11bSBmaXRuZXNzIGFjY3VtdWxhdGlvbiBmb3IgYm90aCBzaSBhbmQgY2kKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwoKYGBge3J9CmV6X2xhYmVsIDwtIHJlYWQuY3N2KGhlcmUoImRhdGEvZXpfbGFiZWwuY3N2IikpCmBgYAoKIyBwcm9jZXNzIHNpbmdsZSBpbmZlY3Rpb24gZGF0YQpgYGB7cn0KIyBpbXBvcnQgaW4gc2kgbWF4aW11bSB0cmFuc21pc3Npb24gcG90ZW50aWFsCnNpX2R5bi5kZiA8LSByZWFkX3BhcnF1ZXQoaGVyZSgiZGF0YS9zaV9keW4vc2lfZHluXzMwLnBhcnF1ZXQiKSkKCiMgZ2V0IG1heGltdW0gdGF1X2N1bSBmb3IgMzAgZGF5cwpzaV9tYXhfdGF1IDwtIHNpX2R5bi5kZiAlPiUgCiAgZmlsdGVyKHZhcmlhYmxlID09ICJ0YXVfY3VtIikgJT4lIAogIGdyb3VwX2J5KGlkKSAlPiUgCiAgc3VtbWFyaXNlKGZpdG5lc3Nfc2kgPSBtYXgodmFsdWUpKQpgYGAKCiMgcHJvY2VzcyBjby1pbmZlY3Rpb24gZGF0YQpgYGB7cn0KIyBpbXBvcnQgaW4gY28taW5mZWNpdG9uIGRhdGEsIDMwIGRheXMgc2ltdWxhdGlvbgpjaV9keW4uZGYgPC0gcmVhZF9wYXJxdWV0KGhlcmUoImRhdGEvY2lfZHluL2NpX2R5bi5wYXJxdWV0IikpCgojIGdldCBtYXhpbXVtIHRhdV9jdW0uIE5vdGUgbXVsdGlwbGllZCBieSAyIHRvIGdldCB0b3RhbCBmaXRuZXNzIGZvciBib3RoIHN0cmFpbnMsIGdpdmVuIHRoYXQgYm90aCBhcmUgc2FkaXB0bmcgdGhlIHNhbWUgc3RyYXRlZ3ksIHdlIGNvbnNpZGVyIHRoZW0gdGhlIHNhbWUgZ2Vub3R5ZQpjaV9tYXhfdGF1IDwtIGNpX2R5bi5kZiAlPiUgCiAgZmlsdGVyKHZhcmlhYmxlID09ICJ0YXVfY3VtMSIpICU+JSAKICBncm91cF9ieShsYWJlbCkgJT4lIAogIHN1bW1hcmlzZShmaXRuZXNzX2NpID0gbWF4KHZhbHVlLCBuYS5ybSA9IFQpKQpgYGAKCiMgZ2V0IGxhYmVsIGFuZCBqb2luIHRvZ2V0aGVyIDIgZGF0YWZyYW1lcwpgYGB7cn0Kc2lfY2lfbWF4X3RhdSA8LSBjaV9tYXhfdGF1ICU+JSAKICBsZWZ0X2pvaW4oZXpfbGFiZWwsIGJ5ID0gYygibGFiZWwiID0gImxhYmVsX2NpIikpICU+JSAKICBsZWZ0X2pvaW4oc2lfbWF4X3RhdSwgYnkgPSBjKCJpZF9zaSIgPSAiaWQiKSkKYGBgCgojIHBsb3QKYGBge3J9Cm9wdF9jdWVfcGwuQiA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gc2lfY2lfbWF4X3RhdSwgYWVzKHggPSBmaXRuZXNzX3NpLCB5ID0gZml0bmVzc19jaSwgY29sb3IgPSBlel9sYWJlbF9zaSwgc2hhcGUgPSBlel9sYWJlbF9zaSksIHNpemUgPSAyLjUpICsKICBnZ3JlcGVsOjpnZW9tX2xhYmVsX3JlcGVsKGRhdGEgPSBzaV9jaV9tYXhfdGF1LCBhZXMobGFiZWwgPSBlel9sYWJlbCwgeCA9IGZpdG5lc3Nfc2ksIHkgPSBmaXRuZXNzX2NpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLHhsaW0gPSBjKC1JbmYsIEluZiksIHlsaW0gPSBjKE5BLCBOQSkpICsKICBsYWJzKHggPSAiT3B0aW1hbCBzaW5nbGUtaW5mZWN0aW9uIGZpdG5lc3MiLCB5ID0gIk9wdGltYWwgQ28taW5mZWN0aW9uIGZpdG5lc3MgKHBlciBzdHJhaW4pIiwKICAgICAgIGNvbG9yID0gIlNpbmdsZSBpbmZlY3Rpb24gY3VlIiwgc2hhcGUgPSAiU2luZ2xlIGluZmVjdGlvbiBjdWUiKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IDE1OjI0KSArCiAgbGltcyh4ID0gYyg4LjUsIDEyLjUpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMTAuNSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgYWxwaGEgPSAwLjUpICsgIyBzaSBnb29kIGN1ZSBjdXRvZmYKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyLjI1LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKyAjIGNpIGdvb2QgY3VlIGN1dG9mZgogIHRoZW1lX2J3KCkgKwogIGNvb3JkX2NhcnRlc2lhbihjbGlwID0gIm9mZiIpICsKICB0aGVtZShwbG90Lm1hcmdpbj1tYXJnaW4ocj0wKSkKCmdnc2F2ZShoZXJlKCJmaWd1cmVzL3JlcG9ydDIxL3NpX2NpX2ZpdG5lc3MucG5nIiksIGhlaWdodCA9IDUpCmBgYAojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojIHRpbWUgc2VyaWVzIGNvbnZlcnNpb24gcmF0ZSAobGluZSBmb3JtKQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwoKIyBzaW5nbGUgaW5mZWN0aW9uCmBgYHtyfQpjcl9zaSA8LSBzaV9keW4uZGYgJT4lIAogIGZpbHRlcih2YXJpYWJsZSA9PSAiY3IiKQoKIyBnb29kIGN1ZSBiYWQgY3VlCnNpX2N1ZV9kdiA8LSBzaV9tYXhfdGF1ICU+JSAKICBtdXRhdGUoY2xhc3NpZmljYXRpb24gPSBjYXNlX3doZW4oCiAgICBmaXRuZXNzX3NpID4gMTAuNSB+ICJIaWdoLXBlcmZvcm1pbmciLAogICAgZml0bmVzc19zaSA8PSAxMC41IH4gIlBvb3ItcGVyZm9ybWluZyIKICApKQoKIyBqb2luIHdpdGggY2xhc3NpZmljYWl0b24KY3Jfc2kuZGYgPC0gY3Jfc2kgJT4lIGxlZnRfam9pbihzaV9jdWVfZHYpICU+JSBsZWZ0X2pvaW4oZXpfbGFiZWwsIGJ5ID0gYygiaWQiID0gImlkX3NpIikpCgojIHNwbGl0IGludG8gdG9wIGVyZm9ybWluZyBhbmQgcG9vci1wZXJmb3JtaW5nIGN1ZXMKY3Jfc2kuaGlnaCA8LSBjcl9zaS5kZiAlPiUgZmlsdGVyKGNsYXNzaWZpY2F0aW9uID09ICJIaWdoLXBlcmZvcm1pbmciKQpjcl9zaS5wb29yIDwtIGNyX3NpLmRmICU+JSBmaWx0ZXIoY2xhc3NpZmljYXRpb24gPT0gIlBvb3ItcGVyZm9ybWluZyIpCgojIHBsb3QKY3Jfc2lfcGwucHJlIDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IGNyX3NpLnBvb3IsIGFlcyh4PSB0aW1lLCB5ID0gdmFsdWUsIGdyb3VwID0gaWQpLCBjb2xvciA9ICJkYXJrIGdyZXkiKSArCiAgbGFicyhjb2xvciA9ICJTaW5nbGUgaW5mZWN0aW9uXG5oaWdoLXBlcmZvcm1pbmcgY3VlcyIsIHggPSAiVGltZSAoZGF5cykiLCB5ID0gIkNvbnZlcnNpb24gcmF0ZSIpICsKICB0aGVtZV9idygpKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgZm9ybWF0KHgsIHNjaWVudGlmaWMgPSBUUlVFLCBhY2N1cmFjeSA9IDAuMSkpICsKICBndWlkZXMoc2hhcGUgPSBGQUxTRSkKCmNyX3NpX3BsIDwtIGNyX3NpX3BsLnByZSArCiAgZ2VvbV9saW5lKGRhdGEgPSBjcl9zaS5oaWdoLCBhZXMoeD0gdGltZSwgeSA9IHZhbHVlLCBncm91cCA9IGV6X2xhYmVsX3NpLCBjb2xvciA9IGV6X2xhYmVsX3NpKSwgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoICIjNDU3NWI0IiwgIiNmYzhkNTkiLCAiI2ZkY2I0NCIsICIjOTFiZmRiIikpCgpgYGAKCiMgY28taW5mZWN0aW9uCmBgYHtyfQojIGdldCByZWxldmVudCB2YXJpYWJsZXMKY3JfY2kgPC0gY2lfZHluLmRmICU+JSAKICBmaWx0ZXIodmFyaWFibGUgPT0gImNyXzEiKQoKIyBnb29kIGN1ZSBiYWQgY3VlCmNpX2N1ZV9kdiA8LSBjaV9tYXhfdGF1ICU+JSAKICBtdXRhdGUoY2xhc3NpZmljYXRpb24gPSBjYXNlX3doZW4oCiAgICBmaXRuZXNzX2NpID4gMi4yNSB+ICJIaWdoLXBlcmZvcm1pbmciLAogICAgZml0bmVzc19jaSA8PSAyLjI1IH4gIlBvb3ItcGVyZm9ybWluZyIKICApKQoKc2lfY3VlX2R2CgojIGpvaW4gd2l0aCBjbGFzc2lmaWNhaXRvbgpjcl9jaS5kZiA8LSBjcl9jaSAlPiUgbGVmdF9qb2luKGNpX2N1ZV9kdiApJT4lIGxlZnRfam9pbihlel9sYWJlbCwgYnkgPSBjKCJsYWJlbCIgPSAibGFiZWxfY2kiKSkKCiMgc3BsaXQgaW50byB0b3AgZXJmb3JtaW5nIGFuZCBwb29yLXBlcmZvcm1pbmcgY3Vlcwpjcl9jaS5oaWdoIDwtIGNyX2NpLmRmICU+JSBmaWx0ZXIoY2xhc3NpZmljYXRpb24gPT0gIkhpZ2gtcGVyZm9ybWluZyIpCmNyX2NpLnBvb3IgPC0gY3JfY2kuZGYgJT4lIGZpbHRlcihjbGFzc2lmaWNhdGlvbiA9PSAiUG9vci1wZXJmb3JtaW5nIikKCiMgcGxvdApjcl9jaV9wbC5wcmUgPC0gZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gY3JfY2kucG9vciwgYWVzKHg9IHRpbWUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBsYWJlbCksIGNvbG9yID0gImRhcmsgZ3JleSIsIGFscGhhID0gMC41KSArCiAgbGFicyhjb2xvciA9ICJDby1pbmZlY3Rpb25cbmhpZ2gtcGVyZm9ybWluZyBjdWVzIiwgeCA9ICJUaW1lIChkYXkpIiwgeSA9ICJDb252ZXJzaW9uIHJhdGUiKSArCiAgdGhlbWVfYncoKSsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIGZvcm1hdCh4LCBzY2llbnRpZmljID0gVFJVRSwgYWNjdXJhY3kgPSAwLjEpKSArCiAgZ3VpZGVzKHNoYXBlID0gRkFMU0UpCgpjcl9jaV9wbCA8LSBjcl9jaV9wbC5wcmUgKwogIGdlb21fbGluZShkYXRhID0gY3JfY2kuaGlnaCwgYWVzKHg9IHRpbWUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBlel9sYWJlbCwgY29sb3IgPSBlel9sYWJlbCksIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCAiIzQ1NzViNCIsICIjZmM4ZDU5IiwgIiNmZGNiNDQiLCAiIzkxYmZkYiIpKQpgYGAKCiMgYXJyYW5nZSB0b2dldGhlcgpgYGB7cn0KY3JfcGwgPC0gZ2dhcnJhbmdlKGNyX3NpX3BsLCBjcl9jaV9wbCwgYWxpZ24gPSAiaHYiLCBuY29sID0gMSkKYGBgCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojIFRpbWUgc2VyaWVzIGNvbnZlcnNpb24gcmF0ZSAoaGVhdG1hcCkKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKbm90ZSB0aGF0IHRoZSBvcmRlciBvZiBjdWVzIGlzIHNvcnRlZCBieSBkZXNjZW5kaW5nIDMwLWRheXMgZml0bmVzcy4KIyBzaW5nbGUgaW5mZWN0aW9uCmBgYHtyfQpjcl9obV9zaS5wbDEgPC0gZ2dwbG90KCkgKwogIGdlb21fdGlsZShkYXRhID0gY3Jfc2kucG9vciwgYWVzKHggPSB0aW1lLCB5ID0gZm9yY2F0czo6ZmN0X3Jlb3JkZXIoZXpfbGFiZWxfc2ksIGZpdG5lc3Nfc2kpLCBmaWxsID0gdmFsdWUpKSArCiAgbGFicyh4ID0gIlRpbWUgKGRheXMpIiwgeSA9ICJMb3cgcGVyZm9ybWluZ1xuc2luZ2xlIGluZmVjdGlvbiBjdWVzIiwgZmlsbCA9ICJDb252ZXJzaW9uIHJhdGUiKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MobGltaXRzID0gYygwLCAxKSkgKwogIHhsaW0oMSwgMzApICsKICB0aGVtZV9idygpCgpjcl9obV9zaS5wbDIgPC0gZ2dwbG90KCkgKwogIGdlb21fdGlsZShkYXRhID0gY3Jfc2kuaGlnaCwgYWVzKHggPSB0aW1lLCB5ID0gZm9yY2F0czo6ZmN0X3Jlb3JkZXIoZXpfbGFiZWxfc2ksIGZpdG5lc3Nfc2kpLCBmaWxsID0gdmFsdWUpKSArCiAgbGFicyh4ID0gIiIsIHkgPSAiSGlnaCBwZXJmb3JtaW5nXG5zaW5nbGUgaW5mZWN0aW9uIGN1ZXMiLCBmaWxsID0gIkNvbnZlcnNpb24gcmF0ZSIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhsaW1pdHMgPSBjKDAsIDEpKSArCiAgeGxpbSgxLCAzMCkgKwogIHRoZW1lX2J3KCkKYGBgCgojIGNvLWluZmVjdGlvbgpgYGB7cn0KY3JfaG1fY2kucGwxIDwtIGdncGxvdCgpICsKICBnZW9tX3RpbGUoZGF0YSA9IGNyX2NpLnBvb3IsIGFlcyh4ID0gdGltZSwgeSA9IGZvcmNhdHM6OmZjdF9yZW9yZGVyKGV6X2xhYmVsLCBmaXRuZXNzX2NpKSwgZmlsbCA9IHZhbHVlKSkgKwogIGxhYnMoeCA9ICJUaW1lIChkYXlzKSIsIHkgPSAiTG93IHBlcmZvcm1pbmdcbmNvLWluZmVjdGlvbiBpbmZlY3Rpb24gY3VlcyIsIGZpbGwgPSAiQ29udmVyc2lvbiByYXRlIikgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKGxpbWl0cyA9IGMoMCwgMSkpICsKICB4bGltKDEsIDMwKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKY3JfaG1fY2kucGwyIDwtIGdncGxvdCgpICsKICBnZW9tX3RpbGUoZGF0YSA9IGNyX2NpLmhpZ2gsIGFlcyh4ID0gdGltZSwgZm9yY2F0czo6ZmN0X3Jlb3JkZXIoZXpfbGFiZWwsIGZpdG5lc3NfY2kpLCBmaWxsID0gdmFsdWUpKSArCiAgbGFicyh4ID0gIiIsIHkgPSAiSGlnaCBwZXJmb3JtaW5nXG5jby1pbmZlY3Rpb24gY3VlcyIsIGZpbGwgPSAiQ29udmVyc2lvbiByYXRlIikgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKGxpbWl0cyA9IGMoMCwgMSkpICsKICB4bGltKDEsIDMwKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKCmNyX2htLnBsIDwtIGdnYXJyYW5nZShjcl9obV9zaS5wbDIsIGNyX2htX2NpLnBsMiwgY3JfaG1fc2kucGwxLCBjcl9obV9jaS5wbDEsIGFsaWduID0gImh2IiwgbmNvbCA9IDIsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVCkKCmdnc2F2ZShoZXJlKCJmaWd1cmVzL3JlcG9ydDIxL2NvbnZlcnNpb25fcmF0ZV9oZWF0bWFwLnBuZyIpLCBoZWlnaHQgPSA1LjUsIHdpZHRoID0gMTIpCmBgYAoKCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCiMgZGlzYXNlIGN1cnZlCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCm5vdGUgd2UgYXJlIHVzaW5nIHRoZSBzYW1lIDMwIGRheXMgaW5mZWN0aW9uIGR5bmFtaWNzIGZyb20gYmVmb3JlCgojIGZvciBzaW5nbGUgaW5mZWN0aW9uCm5vdGUgdGhhdCB3ZSBhcmUgZGl2aWRpbmcgdGhlIGN1ZXMgaW50byBnb29kIGFuZCBiYWQgYmFzZWQgb24gYXJiaXRyYXJ5IGN1dCBvZmYgYXQgMTAuNQpgYGB7cn0KIyBnZXQgcmVsZXZlbnQgdmFyaWFibGVzCmRjX3NpIDwtIHNpX2R5bi5kZiAlPiUgCiAgZmlsdGVyKHZhcmlhYmxlID09ICJJIiB8IHZhcmlhYmxlID09ICJJZyIgfCB2YXJpYWJsZSA9PSAiUiIpCgojIG1vcnBoIGludG8gc2tpbm55IGZvcm1hdApkY19zaS5kZiA8LSB0aWR5cjo6cGl2b3Rfd2lkZXIoZGNfc2ksIG5hbWVzX2Zyb20gPSB2YXJpYWJsZSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSwgaWRfY29scyA9IGModGltZSwgaWQpKSAlPiUgCiAgbXV0YXRlKHRvdGFsID0gSStJZykKCiMgam9pbiB3aXRoIGNsYXNzaWZpY2FpdG9uCmRjX3NpLmRmMiA8LSBkY19zaS5kZiAlPiUgbGVmdF9qb2luKHNpX2N1ZV9kdikKCiMgc3BsaXQgaW50byB0b3AgZXJmb3JtaW5nIGFuZCBwb29yLXBlcmZvcm1pbmcgY3VlcwpkY19zaS5oaWdoIDwtIGRjX3NpLmRmMiAlPiUgZmlsdGVyKGNsYXNzaWZpY2F0aW9uID09ICJIaWdoLXBlcmZvcm1pbmciKQpkY19zaS5wb29yIDwtIGRjX3NpLmRmMiAlPiUgZmlsdGVyKGNsYXNzaWZpY2F0aW9uID09ICJQb29yLXBlcmZvcm1pbmciKQoKIyBqb2luIGhpZ2ggcGVyZm9ybWluZyB3aXRoIGxhYmVsCmRjX3NpLmhpZ2gyIDwtIGRjX3NpLmhpZ2ggJT4lIGxlZnRfam9pbihlel9sYWJlbCAlPiUgZGlzdGluY3QobGFiZWxfc2ksIC5rZWVwX2FsbCA9IFQpLCBieSA9IGMoImlkIiA9ICJpZF9zaSIpKQoKIyBwbG90CmRpc2Vhc2VfY3VydmVfcGwucHJlIDwtIGdncGxvdCgpICsKICBnZW9tX3BhdGgoZGF0YSA9IGRjX3NpLnBvb3IsIGFlcyh4PSB0b3RhbCwgeSA9IFIsIGdyb3VwID0gaWQpLCBjb2xvciA9ICJkYXJrIGdyZXkiLCBhcnJvdyA9IGFycm93KHR5cGUgPSAiY2xvc2VkIiwgYW5nbGUgPSAxMCwgbGVuZ3RoID0gdW5pdCgwLjIsICJpbmNoZXMiKSkpICsKICBsYWJzKGNvbG9yID0gIlNpbmdsZSBpbmZlY3Rpb25cbmhpZ2gtcGVyZm9ybWluZyBjdWVzIiwgeCA9ICJBc2V4dWFsJnNleHVhbCBpUkJDIHBlciBcdTAzYmNMIiwgeSA9ICJSQkMgcGVyIFx1MDNiY0wiKSArCiAgdGhlbWVfYncoKSsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIGZvcm1hdCh4LCBzY2llbnRpZmljID0gVFJVRSwgYWNjdXJhY3kgPSAwLjEpKSArCiAgZ3VpZGVzKHNoYXBlID0gRkFMU0UpCgpkaXNlYXNlX2N1cnZlX3BsLjEgPC0gZGlzZWFzZV9jdXJ2ZV9wbC5wcmUgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRjX3NpLmhpZ2gyICU+JSBmaWx0ZXIocm93X251bWJlcigpICUlIDEwMDAgPT0wKSwgYWVzKHggPSB0b3RhbCwgeSA9IFIsIGNvbG9yID0gZXpfbGFiZWwsIHNoYXBlID0gZXpfbGFiZWwpLCBzaXplID0gMikgKwogIGdlb21fcGF0aChkYXRhID0gZGNfc2kuaGlnaDIsIGFlcyh4PSB0b3RhbCwgeSA9IFIsIGdyb3VwID0gZXpfbGFiZWwsIGNvbG9yID0gZXpfbGFiZWwpLCBzaXplID0gMSwgYXJyb3cgPSBhcnJvdyh0eXBlID0gImNsb3NlZCIsIGFuZ2xlID0gMTAsIGxlbmd0aCA9IHVuaXQoMC4yLCAiaW5jaGVzIikpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCAiIzQ1NzViNCIsICIjZmM4ZDU5IiwgIiNmZGNiNDQiLCAiIzkxYmZkYiIpKSAgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44NSwgMC44KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYuNSksIAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2LjUpKSArCiAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDAuMSkpKQpgYGAKCiMgY28taW5mZWN0aW9uCmBgYHtyfQojIGdldCByZWxldmVudCB2YXJpYWJsZXMKZGNfY2kgPC0gY2lfZHluLmRmICU+JSAKICBmaWx0ZXIodmFyaWFibGUgPT0gIkkxIiB8IHZhcmlhYmxlID09ICJJZzEiIHwgdmFyaWFibGUgPT0gIlIiKQoKIyBtb3JwaCBpbnRvIHNraW5ueSBmb3JtYXQKZGNfY2kuZGYgPC0gdGlkeXI6OnBpdm90X3dpZGVyKGRjX2NpLCBuYW1lc19mcm9tID0gdmFyaWFibGUsIHZhbHVlc19mcm9tID0gdmFsdWUsIGlkX2NvbHMgPSBjKHRpbWUsIGxhYmVsKSkgJT4lIAogIG11dGF0ZSh0b3RhbCA9IEkxK0lnMSkKCiMgZ29vZCBjdWUgYmFkIGN1ZQpjaV9jdWVfZHYgPC0gY2lfbWF4X3RhdSAlPiUgCiAgbXV0YXRlKGNsYXNzaWZpY2F0aW9uID0gY2FzZV93aGVuKAogICAgZml0bmVzc19jaSA+IDQuNSB+ICJIaWdoLXBlcmZvcm1pbmciLAogICAgZml0bmVzc19jaSA8PSA0LjUgfiAiUG9vci1wZXJmb3JtaW5nIgogICkpCgojIGpvaW4gd2l0aCBjbGFzc2lmaWNhaXRvbgpkY19jaS5kZjIgPC0gZGNfY2kuZGYgJT4lIGxlZnRfam9pbihjaV9jdWVfZHYpCgojIHNwbGl0IGludG8gdG9wIGVyZm9ybWluZyBhbmQgcG9vci1wZXJmb3JtaW5nIGN1ZXMKZGNfY2kuaGlnaCA8LSBkY19jaS5kZjIgJT4lIGZpbHRlcihjbGFzc2lmaWNhdGlvbiA9PSAiSGlnaC1wZXJmb3JtaW5nIikKZGNfY2kucG9vciA8LSBkY19jaS5kZjIgJT4lIGZpbHRlcihjbGFzc2lmaWNhdGlvbiA9PSAiUG9vci1wZXJmb3JtaW5nIikKCiMgam9pbiBoaWdoIHBlcmZvcm1pbmcgd2l0aCBsYWJlbApkY19jaS5oaWdoMiA8LSBkY19jaS5oaWdoICU+JSBsZWZ0X2pvaW4oZXpfbGFiZWwsIGJ5ID0gYygibGFiZWwiID0gImxhYmVsX2NpIikpCgojIHBsb3QKZGlzZWFzZV9jdXJ2ZV9wbC5wcmUyIDwtIGdncGxvdCgpICsKICBnZW9tX3BhdGgoZGF0YSA9IGRjX2NpLnBvb3IsIGFlcyh4PSB0b3RhbCwgeSA9IFIsIGdyb3VwID0gbGFiZWwpLCBjb2xvciA9ICJkYXJrIGdyZXkiLCBhcnJvdyA9IGFycm93KHR5cGUgPSAiY2xvc2VkIiwgYW5nbGUgPSAxMCwgbGVuZ3RoID0gdW5pdCgwLjIsICJpbmNoZXMiKSkpICsKICBsYWJzKGNvbG9yID0gIkNvLWluZmVjdGlvblxuaGlnaC1wZXJmb3JtaW5nIGN1ZXMiLCB4ID0gIkFzZXh1YWwmc2V4dWFsIGlSQkMgcGVyIFx1MDNiY0wgKHBlciBzdHJhaW4pIiwgeSA9ICJSQkMgcGVyIFx1MDNiY0wiKSArCiAgdGhlbWVfYncoKSsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIGZvcm1hdCh4LCBzY2llbnRpZmljID0gVFJVRSwgYWNjdXJhY3kgPSAwLjEpKSArCiAgZ3VpZGVzKHNoYXBlID0gRkFMU0UpCgpkaXNlYXNlX2N1cnZlX3BsLjIgPC0gZGlzZWFzZV9jdXJ2ZV9wbC5wcmUyICsKICBnZW9tX3BvaW50KGRhdGEgPSBkY19jaS5oaWdoMiAlPiUgZmlsdGVyKHJvd19udW1iZXIoKSAlJSAxMDAwID09MCksIGFlcyh4ID0gdG90YWwsIHkgPSBSLCBjb2xvciA9IGV6X2xhYmVsLCBzaGFwZSA9IGV6X2xhYmVsKSwgc2l6ZSA9IDIpICsKICBnZW9tX3BhdGgoZGF0YSA9IGRjX2NpLmhpZ2gyLCBhZXMoeD0gdG90YWwsIHkgPSBSLCBncm91cCA9IGV6X2xhYmVsLCBjb2xvciA9IGV6X2xhYmVsKSwgc2l6ZSA9IDEsIGFycm93ID0gYXJyb3codHlwZSA9ICJjbG9zZWQiLCBhbmdsZSA9IDEwLCBsZW5ndGggPSB1bml0KDAuMiwgImluY2hlcyIpKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyggIiM0NTc1YjQiLCAiI2ZjOGQ1OSIsICIjZmRjYjQ0IiwgIiM5MWJmZGIiKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjgpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksIAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSkgKwogIGd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAwLjEpKSkKYGBgCgogIyBwbG90IGJvdGggc2luZ2xlIGFuZCBjby1pbmZlY2l0b24gZGlzZWFzZSBjdXJ2ZSB0b2dldGhlcgpgYGB7cn0KZGlzZWFzZV9jdXJ2ZV9wbCA8LSBnZ2FycmFuZ2UoZGlzZWFzZV9jdXJ2ZV9wbC4xLCBkaXNlYXNlX2N1cnZlX3BsLjIsIGFsaWduID0gImh2IikKZ2dzYXZlKGhlcmUoImZpZ3VyZXMvcmVwb3J0MjEvZGlzZWFzZV9jdXJ2ZS5wbmciKSwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNSkKYGBgCgoKCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKQXJyYW5naW5nIG9wdF9jdWUgZmlndXJlCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKYGBge3J9Cm9wdF9jdWVfcGwuQkMgPC0gZ2dhcnJhbmdlKG9wdF9jdWVfcGwuQiwgY3JfaG0ucGwsIGxhYmVscyA9IGMoIkIiLCAiQyIpLCBuY29sID0gMSwgaGVpZ2h0cyA9IGMoMC43NSwgMSkpCmdnYXJyYW5nZShvcHRfY3VlX3BsLkEsIG9wdF9jdWVfcGwuQkMsIGxhYmVscyA9IGMoIkEiLCAiIiksIG5jb2wgPSAyLCB3aWR0aHMgPSBjKDAuNzUsIDEpKQoKZ2dzYXZlKGhlcmUoImZpZ3VyZXMvcmVwb3J0MjEvb3B0X2N1ZV9maW5hbC5wbmciKSwgd2lkdGggPSAxNCwgaGVpZ2h0ID0gOS41KQpgYGAKCgoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKIyByZW1ha2luZyBoZWF0bWFwcwojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKIyBzdGF0aWMgaGVhdG1hcAojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKIyBwcm9jZXNzaW5nIGRhdGEKYGBge3J9CiMgaW1wb3J0IGluIGRhdGFzZXQKc3RhdGljLmRmIDwtIHJlYWQuY3N2KGhlcmUoImRhdGEvY2lfc3RhdGljLmNzdiIpKQplel9sYWJlbCA8LSByZWFkLmNzdihoZXJlKCJkYXRhL2V6X2xhYmVsLmNzdiIpKQoKIyBqb2luIHdpdGggbGFiZWxsaW5nCnN0YXRpYy5kZjIgPC0gc3RhdGljLmRmICU+JSAKICBsZWZ0X2pvaW4oc2VsZWN0KGV6X2xhYmVsLCBpZF9jaSwgbGFiZWxfY2lfMSA9IGxhYmVsX2NpKSwgYnkgPSBjKCJpZF8xIiA9ICJpZF9jaSIpKSAlPiUgCiAgbGVmdF9qb2luKHNlbGVjdChlel9sYWJlbCwgaWRfY2ksIGxhYmVsX2NpXzIgPSBsYWJlbF9jaSksIGJ5ID0gYygiaWRfMiIgPSAiaWRfY2kiKSkgJT4lIAogIG11dGF0ZShmaXRuZXNzX2RpZmYgPSBmaXRuZXNzXzEgLSBmaXRuZXNzXzIpICU+JSAKICBzZWxlY3QobGFiZWxfY2lfMSwgbGFiZWxfY2lfMiwgZml0bmVzc19kaWZmKQoKIyBnZXQgcmV2ZXJzZSBvcmRlciwgd2hpY2ggaXMgc2ltcGx5IGludm92bGVzIHN3aXRjaGluZyB0aGUgY3VlcyBhcm91bmQgdGhlIG11bHRpcGx5aW5nIHRoZSBmaXRuZXNzIGJ5IG5lZ2F0aXZlIDEKc3RhdGljLmRmMyA8LSBzdGF0aWMuZGYyCm5hbWVzKHN0YXRpYy5kZjMpIDwtIGMoImxhYmVsX2NpXzIiLCAibGFiZWxfY2lfMSIsICJmaXRuZXNzX2RpZmYiKQpzdGF0aWMuZGYzJGZpdG5lc3NfZGlmZiA8LSBzdGF0aWMuZGYyJGZpdG5lc3NfZGlmZiAqIC0xCgojIGpvaW4Kc3RhdGljLmRmNCA8LSByYmluZChzdGF0aWMuZGYyLCBzdGF0aWMuZGYzKQoKIyBnZXQgbWVhbgpzdGF0aWMubWVhbiA8LSBzdGF0aWMuZGY0ICU+JSAKICBncm91cF9ieShsYWJlbF9jaV8xKSAlPiUgCiAgc3VtbWFyaXplKG1lYW5fZml0bmVzcyA9IG1lYW4oZml0bmVzc19kaWZmLCBuYS5ybSA9IFQpKQpgYGAKCiMgZ2V0IGhlYXRtYXAKYGBge3J9CiMgaGVhdG1hcApzdGF0aWMucGwxIDwtIGdncGxvdChkYXRhID0gc3RhdGljLmRmNCwgYWVzKHggPSBsYWJlbF9jaV8yLCB5ID0gbGFiZWxfY2lfMSwgZmlsbCA9IGZpdG5lc3NfZGlmZikpKwogIGdlb21fdGlsZShjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiI2ZjOGQ1OSIsIGhpZ2ggPSAiIzQ1NzViNCIsIG1pZCA9ICJ3aGl0ZSIsIAogICBtaWRwb2ludCA9IDAsIHNwYWNlID0gIkxhYiIsIGxpbSA9IGMoLTAuOTIsIDAuOTIpLCBuYW1lPSJGaXRuZXNzXG5kaWZmZXJlbmNlIikgKwogIHRoZW1lX21pbmltYWwoKSArICAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibGVmdCIsCiAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBoanVzdCA9IDEpLAogIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgcGxvdC5tYXJnaW49bWFyZ2luKHIgPSAwKSkgKyAKICBsYWJzKHggPSAiU3RyYWluIDIgY3VlIiwgeSA9ICJTdHJhaW4gMSBjdWUiKSArCiAgY29vcmRfZml4ZWQoKQoKIyBtZWFuIApzdGF0aWMucGwyIDwtIGdncGxvdCgpICsKICBnZW9tX2JhcihkYXRhID0gIHN0YXRpYy5tZWFuLCBhZXMoeSA9IGxhYmVsX2NpXzEsIHggPSBtZWFuX2ZpdG5lc3MpLCBzdGF0ID0gImlkZW50aXR5IikgKwogIGxhYnMoeSA9ICIiLCB4ID0gIk1lYW4gZml0bmVzc1xuZGlmZmVyZW5jZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwbG90Lm1hcmdpbiA9IG1hcmdpbihsID0gMCksCiAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkKCnN0YXRpYy5wbCA8LSBnZ2FycmFuZ2Uoc3RhdGljLnBsMSwgc3RhdGljLnBsMiwgYWxpZ24gPSAiaHYiLCB3aWR0aHMgPSBjKDEsIDAuMikpCmdnc2F2ZShoZXJlKCJmaWd1cmVzL3JlcG9ydDIxL3N0YXRpY19oZWF0bWFwLnBuZyIpLCB3aWR0aCA9IDEwKQpgYGAKCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojIGNpIGludmFzaW9uIG1hdHJpeAojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKYGBge3J9CiMgaW1wb3J0IGFuZCBwcm9jZXNzIGNpLWludmFzaW9uIGRhdGEKaW52YWRlLmxzIDwtIGxpc3QuZmlsZXMoaGVyZSgiZGF0YS9jaV9pbnZhc2lvbi8iKSwgcGF0dGVybiA9ICIqLmNzdiIsIGZ1bGwubmFtZXMgPSBUKQoKaW52YWRlLmxzMiA8LSBsYXBwbHkoaW52YWRlLmxzLCByZWFkLmNzdikKaW52YWRlLmRmIDwtIGRvLmNhbGwocmJpbmQsIGludmFkZS5sczIpCiN3cml0ZS5jc3YoaW52YWRlLmRmLCByb3cubmFtZXMgPSBGLCBoZXJlKCJkYXRhL2NpX2ludmFzaW9uLmNzdiIpKQppbnZhZGUuZGYgPC0gcmVhZC5jc3YoaGVyZSgiZGF0YS9jaV9pbnZhc2lvbi5jc3YiKSkKYGBgCgojIHNhbml0eSBjaGVjay4gYWxsIGludmFzaW9uIGNvbWJpbmF0aW9uIGhzb3VsZCBoYXZlIGEgZml0bmVzcyBoaWdoZXIgdGhhbiBzdGF0aWMgY29tcGV0aXRpb24KYGBge3J9CnNjX3N0YXRpYy5kZiA8LSBzdGF0aWMuZGYgJT4lIAogIG11dGF0ZShmaXRuZXNzX3N0YXRpYyA9IGZpdG5lc3NfMSAtIGZpdG5lc3NfMikgJT4lIAogIHNlbGVjdChpZF8xLCBpZF8yLCBmaXRuZXNzX3N0YXRpYykKCiMgZ2V0IHJldmVyc2UKc2Nfc3RhdGljLmRmMiA8LSBzY19zdGF0aWMuZGYKc2Nfc3RhdGljLmRmMiRmaXRuZXNzX3N0YXRpYyA8LSBzY19zdGF0aWMuZGYkZml0bmVzc19zdGF0aWMqLTEKbmFtZXMoc2Nfc3RhdGljLmRmMikgPC0gYygiaWRfMiIsICJpZF8xIiwgImZpdG5lc3Nfc3RhdGljIikKCiMgY29tYmluZQpzY19zdGF0aWMuZGYzIDwtIHJiaW5kKHNjX3N0YXRpYy5kZiwgc2Nfc3RhdGljLmRmMikKCiMgbGVmdCBqb2luLiBub25lIG9mIHRoZXNlIGFyZSBodWdlIGFuZCBpbnZhc2lvbiBydW5zIGZvciAyMCBkYXlzIHdoZXJlYXMgc3RhdGljIGNvbXBldGl0aW9uIHJ1bnMgZm9yIDMwIGRheXMuIGxvb2tzIGdvb2QKaW52YWRlLmRmICU+JSAKICBsZWZ0X2pvaW4oc2Nfc3RhdGljLmRmMywgYnkgPSBjKCJtdXRfaWQiPSAiaWRfMSIsICJyZXNfaWQiID0gImlkXzIiKSkgJT4lIAogIG11dGF0ZShpbnZhZGVfc3RhdGljID0gZml0bmVzcyAtIGZpdG5lc3Nfc3RhdGljKSAlPiUgCiAgZmlsdGVyKGludmFkZV9zdGF0aWMgPCAwKQpgYGAKCiMgcHJvY2VzcyBkYXRhIGZvciBpbnZhc2lvbiBtYXRyaXgKYGBge3J9CmludmFkZS5tYXQgPC0gaW52YWRlLmRmICU+JSAKICBncm91cF9ieShWMSA9IHBtaW4obXV0X2lkLCByZXNfaWQpLCBWMiA9IHBtYXgobXV0X2lkLCByZXNfaWQpKSAlPiUgIyBncm91cCBieSBjdWUgY29tcGV0aXRpb24sIGlycmVnYXJkbGVzcyBvZiBvcmRlcgogIG11dGF0ZShpZF9hbHQgPSBwYXN0ZTAoVjEsIFYyKSwKICAgICAgICAgaW52YWRlID0gY2FzZV93aGVuKAogICAgICAgICAgIGZpdG5lc3MgPiAwIH4gImludmFkZSIsCiAgICAgICAgICAgZml0bmVzcyA8IDAgfiAibm90IGludmFkZSIKICAgICAgICAgKSkgJT4lIAogIGdyb3VwX2J5KGlkX2FsdCkgJT4lIAogIG11dGF0ZSgKICAgIG11dF9pc19WMSA9IGNhc2Vfd2hlbigKICAgIG11dF9pZCA9PSBWMSB+ICJWMV9pbnZhZGUiLAogICAgbXV0X2lkICE9IFYxIH4gIlYxX2ludmFkZWQiKSkgJT4lIAogIGFycmFuZ2UoaWRfYWx0KSAlPiUgCiAgc2VsZWN0KGZpdG5lc3MsIFYxLCBWMiwgaWRfYWx0LCBpbnZhZGUsIG11dF9pc19WMSkgJT4lIAogIHRpZHlyOjpwaXZvdF93aWRlcihuYW1lc19mcm9tID0gbXV0X2lzX1YxLCB2YWx1ZXNfZnJvbSA9IGZpdG5lc3MpICU+JSAKICBncm91cF9ieShpZF9hbHQpICU+JSAKICBtdXRhdGUoVjFfaW52YWRlMiA9IGdzdWIoIk5BIiwgIiIsIHBhc3RlMChWMV9pbnZhZGUsIGNvbGxhcHNlID0gIiIpKSwKICAgICAgICAgVjFfaW52YWRlZDIgPSBnc3ViKCJOQSIsICIiLCBwYXN0ZTAoVjFfaW52YWRlZCwgY29sbGFwc2UgPSAiIikpKSAlPiUgCiAgZGlzdGluY3QoaWRfYWx0LCAua2VlcF9hbGwgPSBUKSAlPiUgCiAgbXV0YXRlKAogICAgY2F0ZWdvcnkgPSBjYXNlX3doZW4oCiAgICBWMV9pbnZhZGUyID4gMCAmIFYxX2ludmFkZWQyID4gMCB+ICJNdXR1YWwgaW52YXNpb24iLAogICAgVjFfaW52YWRlMiA+IDAgJiBWMV9pbnZhZGVkMiA8IDAgfiAiT25seSBzdHJhaW4gMSBpbnZhc2lvbiIsCiAgICBWMV9pbnZhZGUyIDwgMCAmIFYxX2ludmFkZWQyID4gMCB+ICJPbmx5IHN0cmFpbiAyIGludmFzaW9uIiwKICAgIFYxX2ludmFkZTIgPCAwICYgVjFfaW52YWRlZDIgPCAwIH4gIk11dHVhbCBub24taW52YXNpb24iCiAgKSkgJT4lIAogIHNlbGVjdChWMSwgVjIsIGludmFzaW9uID0gY2F0ZWdvcnkpCgojIGZvciBwbG90dGluZywgbmVlZCB0byBnZXQgYWxsIHNhbWUgY3VlIHZzIHNhbWUgY3VlLCB3aGljaCB3ZSB3aWxsIHNldCB0byBOQQppbnZhZGUuTkEgPC0gY2JpbmQuZGF0YS5mcmFtZShgVjFgID0gdW5pcXVlKGludmFkZS5tYXQkVjEpLAogICAgICBgVjJgID0gdW5pcXVlKGludmFkZS5tYXQkVjEpLAogICAgICBpbnZhc2lvbiA9IE5BKQoKaW52YWRlLm1hdDIgPC0gcmJpbmQoaW52YWRlLm1hdCwgaW52YWRlLk5BKQoKIyBnZXQgbGFiZWwKaW52YWRlLm1hdDMgPC0gaW52YWRlLm1hdDIgJT4lIAogIGxlZnRfam9pbihzZWxlY3QoZXpfbGFiZWwsIGlkX2NpLCBWMV9sYWJlbCA9IGxhYmVsX2NpKSwgYnkgPSBjKCJWMSIgPSAiaWRfY2kiKSkgJT4lIAogIGxlZnRfam9pbihzZWxlY3QoZXpfbGFiZWwsIGlkX2NpLCBWMl9sYWJlbCA9IGxhYmVsX2NpKSwgYnkgPSBjKCJWMiIgPSAiaWRfY2kiKSkKCiMgcmVvcmRlciBzbyB0aGF0IGdncGxvdCBkbyBub3QgbWVzcyB1cApsaWJyYXJ5KGd0b29scykKCmxldmVscyA8LSBtaXhlZHNvcnQodW5pcXVlKGMoaW52YWRlLm1hdDMkVjFfbGFiZWwsIGludmFkZS5tYXQzJFYyX2xhYmVsKSkpCgppbnZhZGUubWF0NCA8LSByYmluZChpbnZhZGUubWF0MywgCiAgICAgICAgICAgICAgICAgICAgICAgIGludmFkZS5tYXQzICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICByZW5hbWUoVjJfbGFiZWwgPSBWMV9sYWJlbCwgVjFfbGFiZWwgPSBWMl9sYWJlbCkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChWMV9sYWJlbCwgVjJfbGFiZWwsIGludmFzaW9uKSkgJT4lCiAgbXV0YXRlKGFjcm9zcyhlbmRzX3dpdGgoImxhYmVsIiksCiAgICAgICAgICAgICAgICB+ZmFjdG9yKC54LCBsZXZlbHMgPSBsZXZlbHMpKSkgJT4lCiAgZmlsdGVyKGFzLmludGVnZXIoVjFfbGFiZWwpIDwgYXMuaW50ZWdlcihWMl9sYWJlbCkpICU+JQogIG11dGF0ZShWMl9sYWJlbCA9IGZvcmNhdHM6OmZjdF9yZXYoVjJfbGFiZWwpKQoKIyBwbG90CmludmFzaW9uLnBsMSA8LSBnZ3Bsb3QoZGF0YSA9IGludmFkZS5tYXQ0LCBhZXMoeCA9IFYyX2xhYmVsLCB5ID0gVjFfbGFiZWwsIGZpbGwgPSBpbnZhc2lvbikpICsKICBnZW9tX3RpbGUoY29sb3IgPSAiYmxhY2siKSArCiAgdGhlbWVfbWluaW1hbCgpICsgIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsCiAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBoanVzdCA9IDEpLAogIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgcGxvdC5tYXJnaW49bWFyZ2luKHIgPSAwKSkgKyAKICBsYWJzKGZpbGwgPSAiSW52YXNpb24iLCB4ID0gIlN0cmFpbiAyIGN1ZSIsIHkgPSAiU3RyYWluIDEgY3VlIikgKwogICNzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IHJldikgKwogIHNjYWxlX3lfZGlzY3JldGUobGltaXRzID0gcmV2KSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiT25seSBzdHJhaW4gMSBpbnZhc2lvbiIgPSAiIzQ1NzViNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT25seSBzdHJhaW4gMiBpbnZhc2lvbiIgPSAiI2ZjOGQ1OSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTXV0dWFsIGludmFzaW9uIiA9ICIjZmVlMDkwIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKIyBjcmVhdGUgc3VtbWFyeSBiYXIgY2hhcnQKYGBge3J9CiMgY3JlYXRlIGEgc3RhY2tlZCBiYXJjaGFydCBmb3Igc3VtbWFyeQojIyBmaWx0ZXIgb3V0IG5hCmludmFkZS5tYXRhbHQgPC0gaW52YWRlLm1hdDMgJT4lIG5hLmV4Y2x1ZGUoKQoKIyBnZXQgZnJxdWVuY3kgZnJvbSBib3RoIHNpZGVzLiBOb3RlIHdoZW4gZ3JvdXBpbmcgZm9yIFYyLCBmcm9tIHRoZSBwZXJzcGVjdGl2ZSBvZiBjdWUgMiwgc2NlbmFycmlvIHdoZW4gc3RyYWluIDIgaW52YWRlID0gc3RyYWluIDEgaW52YWRlCmludmFkZS5tYXRhbHQxIDwtIGludmFkZS5tYXRhbHQgJT4lIGdyb3VwX2J5KFYxX2xhYmVsLCBpbnZhc2lvbikgJT4lIAogIHN1bW1hcml6ZShmcmVxdWVuY3lfMSA9IG4oKSkKCmludmFkZS5tYXRhbHQyIDwtIGludmFkZS5tYXRhbHQgJT4lCiAgbXV0YXRlKGludmFzaW9uX2FsdCA9IGNhc2Vfd2hlbigKICAgIGludmFzaW9uID09ICJPbmx5IHN0cmFpbiAxIGludmFzaW9uIiB+ICJPbmx5IHN0cmFpbiAyIGludmFzaW9uIiwKICAgIGludmFzaW9uID09ICJPbmx5IHN0cmFpbiAyIGludmFzaW9uIiB+ICJPbmx5IHN0cmFpbiAxIGludmFzaW9uIiwKICAgIGludmFzaW9uID09ICJNdXR1YWwgaW52YXNpb24iIH4gIk11dHVhbCBpbnZhc2lvbiIsCiAgICBpbnZhc2lvbiA9PSAiTXV0dWFsIG5vbi1pbnZhc2lvbiIgfiAiTXV0dWFsIG5vbi1pbnZhc2lvbiIKICApKSAlPiUgCiAgZ3JvdXBfYnkoVjJfbGFiZWwsIGludmFzaW9uX2FsdCkgJT4lIAogIHN1bW1hcml6ZShmcmVxdWVuY3lfMiA9IG4oKSkgICAgIAoKIyBmdWxsIGpvaW4gYW5kIHN1bS4gaGFzIGNvbmZpcm1lZCBhbGwgb2YgdGhlbSBhZGQgdXAgdG8gMTQgCmludmFkZS5tYXRhbHQzIDwtIGZ1bGxfam9pbihpbnZhZGUubWF0YWx0MSwgaW52YWRlLm1hdGFsdDIsIGJ5ID0gYygiVjFfbGFiZWwiID0gIlYyX2xhYmVsIiwgImludmFzaW9uIiA9ICJpbnZhc2lvbl9hbHQiKSkKCmludmFkZS5tYXRhbHQzW2lzLm5hKGludmFkZS5tYXRhbHQzKV0gPC0gMAppbnZhZGUubWF0YWx0NCA8LSBpbnZhZGUubWF0YWx0MyAlPiUgCiAgbXV0YXRlKGZyZXEgPSBmcmVxdWVuY3lfMSArIGZyZXF1ZW5jeV8yKSAlPiUgCiAgbXV0YXRlKHRlbXAgPSBjYXNlX3doZW4oCiAgICBpbnZhc2lvbiA9PSAiT25seSBzdHJhaW4gMSBpbnZhc2lvbiIgfiBmcmVxCiAgKSkgJT4lIAogIGdyb3VwX2J5KFYxX2xhYmVsKSAlPiUgCiAgbXV0YXRlKGludmFkZV8xX2ZyZXEgPSBtYXgodGVtcCwgbmEucm0gPSBUKSkKICAKaW52YXNpb24ucGwyIDwtIGdncGxvdCgpICsKICBnZW9tX2JhcihkYXRhID0gaW52YWRlLm1hdGFsdDQsIGFlcyh4ID0gZnJlcSwgeSA9IHJlb3JkZXIoVjFfbGFiZWwsIGludmFkZV8xX2ZyZXEpLCBmaWxsID0gZm9yY2F0czo6ZmN0X3JldihmYWN0b3IoaW52YXNpb24sIGxldmVscyA9IGMoIk9ubHkgc3RyYWluIDEgaW52YXNpb24iLCAiT25seSBzdHJhaW4gMiBpbnZhc2lvbiIsICJNdXR1YWwgaW52YXNpb24iLCAiTXV0dWFsIG5vbi1pbnZhc2lvbiIpKSkpLCBzdGF0ID0gImlkZW50aXR5IikgKwogIGxhYnMoeCA9ICJGcmVxdWVuY3kiLCBmaWxsID0gIkludmFzaW9uIiwgeSA9ICJTdHJhaW4gMSBjdWUiKSArCiAgdGhlbWVfYncoKSAgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk9ubHkgc3RyYWluIDEgaW52YXNpb24iID0gIiM0NTc1YjQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9ubHkgc3RyYWluIDIgaW52YXNpb24iID0gIiNmYzhkNTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk11dHVhbCBpbnZhc2lvbiIgPSAiI2ZlZTA5MCIpKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQpgYGAKCiMgcGxvdCB0b2dlaHRlcgpgYGB7cn0KaW52YXNpb24ucGwgPC0gZ2dhcnJhbmdlKGludmFzaW9uLnBsMSwgaW52YXNpb24ucGwyLCBhbGlnbiA9ICJoIiwgY29tbW9uLmxlZ2VuZCA9IFQsIHdpZHRocyA9IGMoMiwgMSkpCmdnc2F2ZShoZXJlKCJmaWd1cmVzL3JlcG9ydDIxL2ludmFzaW9uX2hlYXRtYXAucG5nIikpCmBgYAoKCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojIEVmZmVjdCBvZiB2YXJpb3VzIGN1ZSBwZXJjZXB0aW9uCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCiMgc3RhdGljCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwojIGxvZ2dpbmcKYGBge3J9CiMgZ2V0IG5vbi1sb2dnZWQgcGFpcmluZ3MKc3RhdGljX25vbG9nIDwtIHN0YXRpYy5kZjIgJT4lIAogIG11dGF0ZShjdWVfMSA9IHRyaW13cyhnc3ViKCJcXCAuKiIsICIiLCBsYWJlbF9jaV8xKSksCiAgICAgICAgIGxvZ18xID0gY2FzZV93aGVuKAogICAgICAgICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgImxvZyIpIH4gImxvZyIsCiAgICAgICAgICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAibG9nIiwgbmVnYXRlID0gVCkgfiAibm9uZSIpKSAlPiUgCiAgZmlsdGVyKGxvZ18xID09ICJub25lIikKCgpzdGF0aWNfbG9nIDwtIHN0YXRpYy5kZjIgJT4lIAogIG11dGF0ZShjdWVfMSA9IHRyaW13cyhnc3ViKCJcXCAuKiIsICIiLCBsYWJlbF9jaV8xKSksCiAgICAgICAgIGxvZ18xID0gY2FzZV93aGVuKAogICAgICAgICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgImxvZyIpIH4gImxvZyIsCiAgICAgICAgICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAibG9nIiwgbmVnYXRlID0gVCkgfiAibm9uZSIpKSAlPiUgCiAgZmlsdGVyKGxvZ18xID09ICJsb2ciKQoKc3RhdGljX2xvZy5kZiA8LSBsZWZ0X2pvaW4oCiAgc2VsZWN0KHN0YXRpY19ub2xvZywgY3VlXzEsIGxhYmVsX2NpXzIsIGxvZ18xLCBOb25lID0gZml0bmVzc19kaWZmKSwKICBzZWxlY3Qoc3RhdGljX2xvZywgY3VlXzEsIGxhYmVsX2NpXzIsIGxvZ18xLCBMb2cgPSBmaXRuZXNzX2RpZmYpLAogIGJ5ID0gYygiY3VlXzEiLCAibGFiZWxfY2lfMiIpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShOb25lKSAmICFpcy5uYShMb2cpKSAlPiUgCiAgbXV0YXRlKGNsYXNzaWZpY2F0aW9uID0gaWZlbHNlKExvZyA+IE5vbmUsICJMb2dnZWQgYmV0dGVyIiwgIk5vdCBsb2dnZWQgYmV0dGVyIikpCmBgYAoKIyBjb21iaW5lZApgYGB7cn0Kc3RhdGljX25vY29tYiA8LSBzdGF0aWMuZGYyICU+JSAKICBtdXRhdGUoY3VlXzEgPSBpZmVsc2UoCiAgICBzdHJfZGV0ZWN0KGxhYmVsX2NpXzEsICJzdW0iKSwgIkkrSWciLAogICAgdHJpbXdzKGdzdWIoIisxLip8XFwgbG9nIiwgIiIsIGxhYmVsX2NpXzEpKQogICksCiAgbG9nXzEgPSBjYXNlX3doZW4oCiAgICAgICAgICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAibG9nIikgfiAibG9nIiwKICAgICAgICAgICBzdHJfZGV0ZWN0KGxhYmVsX2NpXzEsICJsb2ciLCBuZWdhdGUgPSBUKSB+ICJub25lIiksCiAgICBjb21iXzEgPSBjYXNlX3doZW4oCiAgICBzdHJfZGV0ZWN0KGxhYmVsX2NpXzEsICIxK3xzdW0iKSB+ICJjb21iIiwKICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgIjErfHN1bSIsIG5lZ2F0ZSA9IFQpIH4gIm5vbmUiIAogICkpICU+JSAKICBmaWx0ZXIoY29tYl8xID09ICJub25lIikKCnN0YXRpY19jb21iIDwtIHN0YXRpYy5kZjIgJT4lIAogIG11dGF0ZShjdWVfMSA9IGlmZWxzZSgKICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgInN1bSIpLCAiSStJZyIsCiAgICB0cmltd3MoZ3N1YigiKzEuKnxcXCBsb2ciLCAiIiwgbGFiZWxfY2lfMSkpCiAgKSwKICBsb2dfMSA9IGNhc2Vfd2hlbigKICAgICAgICAgICBzdHJfZGV0ZWN0KGxhYmVsX2NpXzEsICJsb2ciKSB+ICJsb2ciLAogICAgICAgICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgImxvZyIsIG5lZ2F0ZSA9IFQpIH4gIm5vbmUiKSwKICAgIGNvbWJfMSA9IGNhc2Vfd2hlbigKICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgIjErfHN1bSIpIH4gImNvbWIiLAogICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAiMSt8c3VtIiwgbmVnYXRlID0gVCkgfiAibm9uZSIgCiAgKSkgJT4lIAogIGZpbHRlcihjb21iXzEgPT0gImNvbWIiKQogIApzdGF0aWNfY29tYi5kZiA8LSBsZWZ0X2pvaW4oCiAgc2VsZWN0KHN0YXRpY19ub2NvbWIsIGN1ZV8xLCBsYWJlbF9jaV8yLCBsb2dfMSwgU2VsZiA9IGZpdG5lc3NfZGlmZiksCiAgc2VsZWN0KHN0YXRpY19jb21iLCBjdWVfMSwgbGFiZWxfY2lfMiwgbG9nXzEsIFRvdGFsID0gZml0bmVzc19kaWZmKSwKICBieSA9IGMoImN1ZV8xIiwgImxvZ18xIiwgImxhYmVsX2NpXzIiKSkgJT4lIAogIGZpbHRlcighaXMubmEoVG90YWwpICYgIWlzLm5hKFNlbGYpKSAlPiUgCiAgbXV0YXRlKGNsYXNzaWZpY2F0aW9uID0gaWZlbHNlKFRvdGFsID4gU2VsZiwgIlRvdGFsIGJldHRlciIsICJTZWxmIGJldHRlciIpKQpgYGAKCiMgcGxvdApgYGB7cn0Kc3RhdGljX2xvZy5wbCA8LSBnZ3BhaXJlZChzdGF0aWNfbG9nLmRmLCBjb25kMSA9ICJOb25lIiwgY29uZDIgPSAiTG9nIiwgbGluZS5jb2xvciA9ICJjbGFzc2lmaWNhdGlvbiIsIGFscGhhID0gMC41KSArCiAgbGFicyh4ID0gIkN1ZSBwZXJjZXB0aW9uIiwgeSA9ICJGaXRuZXNzIGRpZmZlcmVuY2UiLCBjb2xvciA9ICJFZmZlY3QiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk5vdCBsb2dnZWQgYmV0dGVyIiA9ICIjZmM4ZDU5IiwgIkxvZ2dlZCBiZXR0ZXIiID0gIiM0NTc1YjQiKSkKCnN0YXRpY19jb21iLnBsIDwtIGdncGFpcmVkKHN0YXRpY19jb21iLmRmLCBjb25kMSA9ICJUb3RhbCIsIGNvbmQyID0gIlNlbGYiLCBsaW5lLmNvbG9yID0gImNsYXNzaWZpY2F0aW9uIiwgYWxwaGEgPSAwLjUpICsKICBsYWJzKHggPSAiQ3VlIHBlcmNlcHRpb24iLCB5ID0gIkZpdG5lc3MgZGlmZmVyZW5jZSIsIGNvbG9yID0gIkVmZmVjdCIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiVG90YWwgYmV0dGVyIiA9ICIjZmM4ZDU5IiwgIlNlbGYgYmV0dGVyIiA9ICIjNDU3NWI0IikpCgpzdGF0aWNfY3VlLnBsIDwtIGdnYXJyYW5nZShzdGF0aWNfbG9nLnBsLCBzdGF0aWNfY29tYi5wbCwgbmNvbCA9IDIsIGFsaWduID0gImgiKQpnZ3NhdmUoaGVyZSgiZmlndXJlcy9yZXBvcnQyMS9zdGF0aWNfY3VlLnBuZyIpLCB3aWR0aCA9IDcuNSwgaGVpZ2h0ID0gNCkKYGBgCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCiMgaW52YXNpb24KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIwpgYGB7cn0KIyBqb2luIGludmFkZSBkZiB3aXRoIGxhYmVsIGJlY2F1c2UgSSBhbSBsYXp5CmludmFkZS5kZjIgPC0gaW52YWRlLmRmICU+JSAKICBsZWZ0X2pvaW4oc2VsZWN0KGV6X2xhYmVsLCBpZF9jaSwgbGFiZWxfY2lfMSA9IGxhYmVsX2NpKSwgYnkgPSBjKCJtdXRfaWQiID0gImlkX2NpIikpCmBgYAoKIyBsb2cKYGBge3J9CiMgZ2V0IG5vbi1sb2dnZWQgcGFpcmluZ3MKaW52YWRlX25vbG9nIDwtIGludmFkZS5kZjIgJT4lIAogIG11dGF0ZShjdWVfMSA9IHRyaW13cyhnc3ViKCJcXCAuKiIsICIiLCBsYWJlbF9jaV8xKSksCiAgICAgICAgIGxvZ18xID0gY2FzZV93aGVuKAogICAgICAgICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgImxvZyIpIH4gImxvZyIsCiAgICAgICAgICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAibG9nIiwgbmVnYXRlID0gVCkgfiAibm9uZSIpKSAlPiUgCiAgZmlsdGVyKGxvZ18xID09ICJub25lIikKCgppbnZhZGVfbG9nIDwtIGludmFkZS5kZjIgJT4lIAogIG11dGF0ZShjdWVfMSA9IHRyaW13cyhnc3ViKCJcXCAuKiIsICIiLCBsYWJlbF9jaV8xKSksCiAgICAgICAgIGxvZ18xID0gY2FzZV93aGVuKAogICAgICAgICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgImxvZyIpIH4gImxvZyIsCiAgICAgICAgICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAibG9nIiwgbmVnYXRlID0gVCkgfiAibm9uZSIpKSAlPiUgCiAgZmlsdGVyKGxvZ18xID09ICJsb2ciKQoKaW52YWRlX2xvZy5kZiA8LSBsZWZ0X2pvaW4oCiAgc2VsZWN0KGludmFkZV9ub2xvZywgY3VlXzEsIHJlc19pZCwgbG9nXzEsIE5vbmUgPSBmaXRuZXNzKSwKICBzZWxlY3QoaW52YWRlX2xvZywgY3VlXzEsIHJlc19pZCwgbG9nXzEsIExvZyA9IGZpdG5lc3MpLAogIGJ5ID0gYygiY3VlXzEiLCAicmVzX2lkIikpICU+JSAKICBmaWx0ZXIoIWlzLm5hKE5vbmUpICYgIWlzLm5hKExvZykpICU+JSAKICBtdXRhdGUoY2xhc3NpZmljYXRpb24gPSBpZmVsc2UoTG9nID4gTm9uZSwgIkxvZ2dlZCBiZXR0ZXIiLCAiTm90IGxvZ2dlZCBiZXR0ZXIiKSkKYGBgCgojIGNvbWJpbmVkCmBgYHtyfQppbnZhZGVfbm9jb21iIDwtIGludmFkZS5kZjIgJT4lIAogIG11dGF0ZShjdWVfMSA9IGlmZWxzZSgKICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgInN1bSIpLCAiSStJZyIsCiAgICB0cmltd3MoZ3N1YigiKzEuKnxcXCBsb2ciLCAiIiwgbGFiZWxfY2lfMSkpCiAgKSwKICBsb2dfMSA9IGNhc2Vfd2hlbigKICAgICAgICAgICBzdHJfZGV0ZWN0KGxhYmVsX2NpXzEsICJsb2ciKSB+ICJsb2ciLAogICAgICAgICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgImxvZyIsIG5lZ2F0ZSA9IFQpIH4gIm5vbmUiKSwKICAgIGNvbWJfMSA9IGNhc2Vfd2hlbigKICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgIjErfHN1bSIpIH4gImNvbWIiLAogICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAiMSt8c3VtIiwgbmVnYXRlID0gVCkgfiAibm9uZSIgCiAgKSkgJT4lIAogIGZpbHRlcihjb21iXzEgPT0gIm5vbmUiKQoKaW52YWRlX2NvbWIgPC0gaW52YWRlLmRmMiAlPiUgCiAgbXV0YXRlKGN1ZV8xID0gaWZlbHNlKAogICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAic3VtIiksICJJK0lnIiwKICAgIHRyaW13cyhnc3ViKCIrMS4qfFxcIGxvZyIsICIiLCBsYWJlbF9jaV8xKSkKICApLAogIGxvZ18xID0gY2FzZV93aGVuKAogICAgICAgICAgIHN0cl9kZXRlY3QobGFiZWxfY2lfMSwgImxvZyIpIH4gImxvZyIsCiAgICAgICAgICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAibG9nIiwgbmVnYXRlID0gVCkgfiAibm9uZSIpLAogICAgY29tYl8xID0gY2FzZV93aGVuKAogICAgc3RyX2RldGVjdChsYWJlbF9jaV8xLCAiMSt8c3VtIikgfiAiY29tYiIsCiAgICBzdHJfZGV0ZWN0KGxhYmVsX2NpXzEsICIxK3xzdW0iLCBuZWdhdGUgPSBUKSB+ICJub25lIiAKICApKSAlPiUgCiAgZmlsdGVyKGNvbWJfMSA9PSAiY29tYiIpCiAgCmludmFkZV9jb21iLmRmIDwtIGxlZnRfam9pbigKICBzZWxlY3QoaW52YWRlX25vY29tYiwgY3VlXzEsIHJlc19pZCwgbG9nXzEsIFNlbGYgPSBmaXRuZXNzKSwKICBzZWxlY3QoaW52YWRlX2NvbWIsIGN1ZV8xLCByZXNfaWQsIGxvZ18xLCBUb3RhbCA9IGZpdG5lc3MpLAogIGJ5ID0gYygiY3VlXzEiLCAibG9nXzEiLCAicmVzX2lkIikpICU+JSAKICBmaWx0ZXIoIWlzLm5hKFRvdGFsKSAmICFpcy5uYShTZWxmKSkgJT4lIAogIG11dGF0ZShjbGFzc2lmaWNhdGlvbiA9IGlmZWxzZShUb3RhbCA+IFNlbGYsICJUb3RhbCBiZXR0ZXIiLCAiU2VsZiBiZXR0ZXIiKSkKYGBgCgojIHBsb3QuIG5ldmVybWluZCBqdXN0IGFzc2VtYmxlIGluIGlsbHVzdHJhdG9yCmBgYHtyfQppbnZhZGVfbG9nLnBsIDwtIGdncGFpcmVkKGludmFkZV9sb2cuZGYsIGNvbmQxID0gIk5vbmUiLCBjb25kMiA9ICJMb2ciLCBsaW5lLmNvbG9yID0gImNsYXNzaWZpY2F0aW9uIiwgYWxwaGEgPSAwLjUpICsKICBsYWJzKHggPSAiQ3VlIHBlcmNlcHRpb24iLCB5ID0gIkZpdG5lc3MgZGlmZmVyZW5jZSIsIGNvbG9yID0gIkVmZmVjdCIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiTm90IGxvZ2dlZCBiZXR0ZXIiID0gIiNmYzhkNTkiLCAiTG9nZ2VkIGJldHRlciIgPSAiIzQ1NzViNCIpKQoKaW52YWRlX2NvbWIucGwgPC0gZ2dwYWlyZWQoaW52YWRlX2NvbWIuZGYsIGNvbmQxID0gIlRvdGFsIiwgY29uZDIgPSAiU2VsZiIsIGxpbmUuY29sb3IgPSAiY2xhc3NpZmljYXRpb24iLCBhbHBoYSA9IDAuNSkgKwogIGxhYnMoeCA9ICJDdWUgcGVyY2VwdGlvbiIsIHkgPSAiRml0bmVzcyBkaWZmZXJlbmNlIiwgY29sb3IgPSAiRWZmZWN0IikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJUb3RhbCBiZXR0ZXIiID0gIiNmYzhkNTkiLCAiU2VsZiBiZXR0ZXIiID0gIiM0NTc1YjQiKSkKCmludmFkZV9jdWUucGwgPC0gZ2dhcnJhbmdlKGludmFkZV9sb2cucGwsIGludmFkZV9jb21iLnBsLCBhbGlnbiA9ICJoIiwgbmNvbCA9IDIpCmdnc2F2ZShoZXJlKCJmaWd1cmVzL3JlcG9ydDIxL2ludmFkZV9jdWUucG5nIiksIHdpZHRoID0gNy41LCBoZWlnaHQgPSA0KQpgYGAKCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCiMgYXJyYW5nZSBjby1pbmZlY3Rpb24gZmlndXJlCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKYGBge3J9CmdnYXJyYW5nZShzdGF0aWMucGwsIHN0YXRpY19jdWUucGwsIGludmFzaW9uLnBsLCBpbnZhZGVfY3VlLnBsLCB3aWR0aHMgPSBjKDEuNSwgMSksIGFsaWduID0gImh2IiwgbGFiZWxzID0gYygiQSIsICIiLCAiQiIsICIiKSkKCmdnc2F2ZShoZXJlKCJmaWd1cmVzL3JlcG9ydDIxL2NvaW5mZWN0aW9uX2ZpbmFsLnBuZyIpLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSAxMikKYGBgCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCiMgb3JnYW5pemF0aW9uIGR1YWwgY3VlIG9wdGltaXphdGlvbiBkYXRhCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCmBgYHtyfQpkdWFsX2N1ZS5scyA8LSBsaXN0LmZpbGVzKGhlcmUoImRhdGEvZHVhbF9jdWVfb3B0LyIpLCBwYXR0ZXJuICA9ICIqLmNzdiIsIGZ1bGwubmFtZXMgPSBUKQoKZHVhbF9jdWUubHMyIDwtIGxhcHBseShkdWFsX2N1ZS5scywgcmVhZC5jc3YpCgpkdWFsX2N1ZS5kZiA8LSBkby5jYWxsKHJiaW5kLCBkdWFsX2N1ZS5sczIpCgojIGZpbHRlciBvdXQgdGhvc2UgdGhhdCBkaWQgbm90IG9wdGltaXplIHByb3Blcmx5CmR1YWxfY3VlLmRmMiA8LSBkdWFsX2N1ZS5kZiAlPiUgZmlsdGVyKGZpdG5lc3MgPiAxKQpgYGAKCiMgY2hlY2sgaWYgZml0bmVzcyBvZiB0aGUgZHVhbCBjdWUgaXMgYmV0dGVyIHRoYW4gaW5kaXZpZHVhbC4gMTcgb3V0IG9mIDI1IGNvbXBhcmlzb25zIGhhdmUgbG93ZXIgZml0bmVzcyBsb2wgd2hlbiBvcHRpbWl6ZWQgdmlhIGR1YWwgY3VlLiBOb3Qgc3VyZSB3aGF0IGNvdWxkIHJlbWVkeSB0aGlzLiBTbWFsbGVyIGN1ZSBzdGVwcz8KCiMgZHVhbCBjdWUgaW1wcm92ZWQgdGhlIGZpdG5lc3Mgb2YgdGhlIGZvbGxvd2luZyBjb21iaW5hdGlvbi4gbm90ZSBtYW55IG9mIHRoZXNlIGNvbXBhcmlzb25zIGFyZSBtYWRlIHdoZW4gdGltZSBzdGVwcyBhcmUgZGlmZmVyZW50LiBOZWVkIHRvIG1vZGlmeSBvcHRpbWl6YXRpb24gc28gdGhhdCB0aW1lIHNjYWxlIGlzIHRoZSBzYW1lLiBXZSBzaG91bGQgYWxzbyBiZSBjb21wYXJpbmcgZml0bmVzcyBhdCAzMCBkYXlzIHdoZW4gZnVsbCByZXNvbHV0aW9uIGlzIGFjaGlldmVkLiAKMSkgR19sb2cgYW5kIElfbG9nCjIpIEdfbm9uZSwgSV9sb2cKMykgSWdfbG9nIGFuZCBJX2xvZwo0KSBJZ19ub25lLCBJX2xvZwo1KSBSX2xvZywgSV9sb2cKNikgUl9ub25lLCBJX2xvZwo3KSBSX25vbmUsIElnX25vbmUKCklfbG9nIGlzIGEgcmVhY2N1cmluZyB0aGVtZSBoZXJlLgpgYGB7cn0KZHVhbF9jdWUuZGYyICU+JSAKICBsZWZ0X2pvaW4oc2VsZWN0KHNpX29wdC5kZiwgaWQsIGZpdG5lc3Nfc2kgPSBmaXRuZXNzXzIwKSwgYnkgPSBjKCJpZCIgPSAiaWQiKSkgJT4lIAogIGxlZnRfam9pbihzZWxlY3Qoc2lfb3B0LmRmLCBpZCwgZml0bmVzc19zaV9iID0gZml0bmVzc18yMCksIGJ5ID0gYygiaWRfYiIgPSAiaWQiKSkgJT4lIAogIG11dGF0ZShmaXRuZXNzX2RpZmYgPSBmaXRuZXNzIC0gZml0bmVzc19zaSwKICAgICAgICAgZml0bmVzc19kaWZmX2IgPSBmaXRuZXNzIC0gZml0bmVzc19zaV9iKSAlPiUgCiAgZmlsdGVyKGZpdG5lc3NfZGlmZiA+IDAgJiBmaXRuZXNzX2RpZmZfYiA+IDApCmBgYAoKCiMgcGxvdHRpbmcgb3V0IHNvbWUgaW50ZXJlc3RpbmcgaGVhdG1hcHMKYGBge3J9CnNvdXJjZShoZXJlKCJmdW5jdGlvbnMvcGFyX3RvX2htLlIiKSkKCiMgRyBsb2cgYW5kIEkgbG9nCnBhcl90b19obShwYXIgPSBjKC0wLjUzNTU2ODIyMSwJLTIuNTAxOTEwOSwJNS4zODEyMTMyLAkxLjg5Mjg0NDksCTAuMjM0NTEyNDMpLAogICAgICAgICAgY3VlX3JhbmdlID0gc2VxKDAsCTQuNzc4MTUxMjUsIGxlbmd0aC5vdXQgPSA1MDApLAogICAgICAgICAgY3VlX3JhbmdlX2IgPSBzZXEoMCwJNi43NzgxNTEyNSwJbGVuZ3RoLm91dCA9IDUwMCksCiAgICAgICAgICBwbG90ID0gVCkKCgojIElnX2xvZyBhbmQgSV9sb2cKcGFyX3RvX2htKHBhciA9IGMoLTAuMjUzNTMzMDEzLAktMy4xMDc4MDM1LAk3LjgyMDMxMzQsCTAuMzYwMzUyNCwJLTMuNTEzODk0NjIpLAogICAgICAgICAgY3VlX3JhbmdlID0gc2VxKDAsCTYuNzc4MTUxMjUsIGxlbmd0aC5vdXQgPSA1MDApLAogICAgICAgICAgY3VlX3JhbmdlX2IgPSBzZXEoMCwJNi43NzgxNTEyNSxsZW5ndGgub3V0ID0gNTAwKSwKICAgICAgICAgIHBsb3QgPSBUKQoKIyBSX2xvZywgSV9sb2cKcGFyX3RvX2htKHBhciA9IGMoNS4yNDkyNjQwMzMJLDguOTE3NDkzNywJLTUyLjYyODE1NDkJLC0yMS4xMjg4NzEyLAktMTMuMDUwODAwODQpLAogICAgICAgICAgY3VlX3JhbmdlID0gc2VxKDYsCTcsCWxlbmd0aC5vdXQgPSA1MDApLAogICAgICAgICAgY3VlX3JhbmdlX2IgPSBzZXEoMCwJNi43NzgxNTEyNSxsZW5ndGgub3V0ID0gNTAwKSwKICAgICAgICAgIHBsb3QgPSBUKQoKYGBgCgoKCgoKCgo=